o
    8Va                     @   s  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 d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZmZ d dlmZmZmZ d dlmZ d dlm Z m!Z! d dl"m#Z#m$Z$ d dl%m&Z& d dl'm(Z( d dl)m*Z* d dl+m,Z, G dd deZ-G dd de-edZ.G dd de-Z/G dd de/Z0G dd de/Z1G dd  d e-Z2d*d"d#Z3G d$d% d%e-Z4G d&d' d'e4Z5G d(d) d)e4Z6d!S )+    )Basic)cacheit)is_sequenceiterableordered)Tuple)call_highest_priority)global_parameters)AppliedUndefMul)Integer)Eq)S	Singleton)DummySymbolWildsympify)lcmfactor)IntervalIntersection)simplify)Idx)flatten)expandc                   @   s  e Zd ZdZdZdZed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edd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zed$d%d& Zd'd( Zed)d*d+ Zd,d- Zd.d/ Zed0d1d2 Zd3d4 Z d5d6 Z!d:d8d9Z"d7S );SeqBasezBase class for sequencesT   c              
   C   s.   z| j }W |S  tttfy   tj}Y |S w )z[Return start (if possible) else S.Infinity.

        adapted from Set._infimum_key
        )startNotImplementedErrorAttributeError
ValueErrorr   Infinity)exprr     r&   8/usr/lib/python3/dist-packages/sympy/series/sequences.py
_start_key!   s   
zSeqBase._start_keyc                 C   s   t | j|j}|j|jfS )zTReturns start and stop.

        Takes intersection over the two intervals.
        )r   intervalinfsup)selfotherr)   r&   r&   r'   _intersect_interval.   s   zSeqBase._intersect_intervalc                 C      t d|  )z&Returns the generator for the sequencez(%s).genr!   r,   r&   r&   r'   gen6      zSeqBase.genc                 C   r/   )z-The interval on which the sequence is definedz(%s).intervalr0   r1   r&   r&   r'   r)   ;   r3   zSeqBase.intervalc                 C   r/   ):The starting point of the sequence. This point is includedz
(%s).startr0   r1   r&   r&   r'   r    @   r3   zSeqBase.startc                 C   r/   )z8The ending point of the sequence. This point is includedz	(%s).stopr0   r1   r&   r&   r'   stopE   r3   zSeqBase.stopc                 C   r/   )zLength of the sequencez(%s).lengthr0   r1   r&   r&   r'   lengthJ   r3   zSeqBase.lengthc                 C      dS )z-Returns a tuple of variables that are boundedr&   r&   r1   r&   r&   r'   	variablesO   s   zSeqBase.variablesc                    s    fdd j D S )aG  
        This method returns the symbols in the object, excluding those
        that take on a specific value (i.e. the dummy symbols).

        Examples
        ========

        >>> from sympy import SeqFormula
        >>> from sympy.abc import n, m
        >>> SeqFormula(m*n**2, (n, 0, 5)).free_symbols
        {m}
        c                    s$   h | ]}|j  jD ]}|qqS r&   )free_symbols
differencer8   ).0ijr1   r&   r'   	<setcomp>b   s    z'SeqBase.free_symbols.<locals>.<setcomp>argsr1   r&   r1   r'   r9   T   s   zSeqBase.free_symbolsc                 C   s0   || j k s
|| jkrtd|| jf | |S )z#Returns the coefficient at point ptzIndex %s out of bounds %s)r    r5   
IndexErrorr)   _eval_coeffr,   ptr&   r&   r'   coeffe   s   
zSeqBase.coeffc                 C   s   t d| j )NzhThe _eval_coeff method should be added to%s to return coefficient so it is availablewhen coeff calls it.)r!   funcrC   r&   r&   r'   rB   l   s   zSeqBase._eval_coeffc                 C   s<   | j tju r
| j}n| j }| j tju rd}nd}|||  S )a  Returns the i'th point of a sequence.

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

        If start point is negative infinity, point is returned from the end.
        Assumes the first point to be indexed zero.

        Examples
        =========

        >>> from sympy import oo
        >>> from sympy.series.sequences import SeqPer

        bounded

        >>> SeqPer((1, 2, 3), (-10, 10))._ith_point(0)
        -10
        >>> SeqPer((1, 2, 3), (-10, 10))._ith_point(5)
        -5

        End is at infinity

        >>> SeqPer((1, 2, 3), (0, oo))._ith_point(5)
        5

        Starts at negative infinity

        >>> SeqPer((1, 2, 3), (-oo, 0))._ith_point(5)
        -5
           )r    r   NegativeInfinityr5   )r,   r<   initialstepr&   r&   r'   
_ith_pointr   s    zSeqBase._ith_pointc                 C   r7   )aI  
        Should only be used internally.

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

        self._add(other) returns a new, term-wise added sequence if self
        knows how to add with other, otherwise it returns ``None``.

        ``other`` should only be a sequence object.

        Used within :class:`SeqAdd` class.
        Nr&   r,   r-   r&   r&   r'   _add      zSeqBase._addc                 C   r7   )aS  
        Should only be used internally.

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

        self._mul(other) returns a new, term-wise multiplied sequence if self
        knows how to multiply with other, otherwise it returns ``None``.

        ``other`` should only be a sequence object.

        Used within :class:`SeqMul` class.
        Nr&   rM   r&   r&   r'   _mul   rO   zSeqBase._mulc                 C   s
   t | |S )a  
        Should be used when ``other`` is not a sequence. Should be
        defined to define custom behaviour.

        Examples
        ========

        >>> from sympy import SeqFormula
        >>> from sympy.abc import n
        >>> SeqFormula(n**2).coeff_mul(2)
        SeqFormula(2*n**2, (n, 0, oo))

        Notes
        =====

        '*' defines multiplication of sequences with sequences only.
        r   rM   r&   r&   r'   	coeff_mul   s   
zSeqBase.coeff_mulc                 C   $   t |tstdt| t| |S )a4  Returns the term-wise addition of 'self' and 'other'.

        ``other`` should be a sequence.

        Examples
        ========

        >>> from sympy import SeqFormula
        >>> from sympy.abc import n
        >>> SeqFormula(n**2) + SeqFormula(n**3)
        SeqFormula(n**3 + n**2, (n, 0, oo))
        zcannot add sequence and %s
isinstancer   	TypeErrortypeSeqAddrM   r&   r&   r'   __add__   s   

zSeqBase.__add__rX   c                 C   s   | | S Nr&   rM   r&   r&   r'   __radd__      zSeqBase.__radd__c                 C   s&   t |tstdt| t| | S )a7  Returns the term-wise subtraction of ``self`` and ``other``.

        ``other`` should be a sequence.

        Examples
        ========

        >>> from sympy import SeqFormula
        >>> from sympy.abc import n
        >>> SeqFormula(n**2) - (SeqFormula(n))
        SeqFormula(n**2 - n, (n, 0, oo))
        zcannot subtract sequence and %srS   rM   r&   r&   r'   __sub__   s   
zSeqBase.__sub__r\   c                 C   s
   |  | S rY   r&   rM   r&   r&   r'   __rsub__      
zSeqBase.__rsub__c                 C   s
   |  dS )zNegates the sequence.

        Examples
        ========

        >>> from sympy import SeqFormula
        >>> from sympy.abc import n
        >>> -SeqFormula(n**2)
        SeqFormula(-n**2, (n, 0, oo))
        rG   )rQ   r1   r&   r&   r'   __neg__   s   
zSeqBase.__neg__c                 C   rR   )a{  Returns the term-wise multiplication of 'self' and 'other'.

        ``other`` should be a sequence. For ``other`` not being a
        sequence see :func:`coeff_mul` method.

        Examples
        ========

        >>> from sympy import SeqFormula
        >>> from sympy.abc import n
        >>> SeqFormula(n**2) * (SeqFormula(n))
        SeqFormula(n**3, (n, 0, oo))
        zcannot multiply sequence and %s)rT   r   rU   rV   SeqMulrM   r&   r&   r'   __mul__	  s   

zSeqBase.__mul__ra   c                 C   s   | | S rY   r&   rM   r&   r&   r'   __rmul__  r[   zSeqBase.__rmul__c                 c   s,    t | jD ]}| |}| |V  qd S rY   )ranger6   rL   rE   )r,   r<   rD   r&   r&   r'   __iter__  s
   
zSeqBase.__iter__c                    st   t |tr |} |S t |tr8|j|j}}|d u r!d}|d u r( j} fddt|||j	p4dD S d S )Nr   c                    s   g | ]
}   |qS r&   )rE   rL   )r;   r<   r1   r&   r'   
<listcomp>.      z'SeqBase.__getitem__.<locals>.<listcomp>rH   )
rT   intrL   rE   slicer    r5   r6   rc   rK   )r,   indexr    r5   r&   r1   r'   __getitem__$  s   




zSeqBase.__getitem__Nc                 C   s(  ddl m} dd | d| D }t|}|du r|d }nt||d }g }td|d D ]r}	d|	 }
g }t|	D ]}|||||	   q:||}| dkrt||||	|
 }||
krnt	|ddd } n3g }t|	||	 D ]}|||||	   qw||}|| |||
d krt	|ddd } nq.|du r|S t|}	|	dkrg dfS ||	d  ||	d   d||	d  ||	   }}t|	d D ]5}||| ||  7 }t|	| d D ]}||| ||  ||| d   8 }q||| ||d   8 }q|tt
|t
| fS )	a  
        Finds the shortest linear recurrence that satisfies the first n
        terms of sequence of order `\leq` ``n/2`` if possible.
        If ``d`` is specified, find shortest linear recurrence of order
        `\leq` min(d, n/2) if possible.
        Returns list of coefficients ``[b(1), b(2), ...]`` corresponding to the
        recurrence relation ``x(n) = b(1)*x(n-1) + b(2)*x(n-2) + ...``
        Returns ``[]`` if no recurrence is found.
        If gfvar is specified, also returns ordinary generating function as a
        function of gfvar.

        Examples
        ========

        >>> from sympy import sequence, sqrt, oo, lucas
        >>> from sympy.abc import n, x, y
        >>> sequence(n**2).find_linear_recurrence(10, 2)
        []
        >>> sequence(n**2).find_linear_recurrence(10)
        [3, -3, 1]
        >>> sequence(2**n).find_linear_recurrence(10)
        [2]
        >>> sequence(23*n**4+91*n**2).find_linear_recurrence(10)
        [5, -10, 10, -5, 1]
        >>> sequence(sqrt(5)*(((1 + sqrt(5))/2)**n - (-(1 + sqrt(5))/2)**(-n))/5).find_linear_recurrence(10)
        [1, 1]
        >>> sequence(x+y*(-2)**(-n), (n, 0, oo)).find_linear_recurrence(30)
        [1/2, 1/2]
        >>> sequence(3*5**n + 12).find_linear_recurrence(20,gfvar=x)
        ([6, -5], 3*(5 - 21*x)/((x - 1)*(5*x - 1)))
        >>> sequence(lucas(n)).find_linear_recurrence(15,gfvar=x)
        ([1, 1], (x - 2)/(x**2 + x - 1))
        r   )Matrixc                 S   s   g | ]}t t|qS r&   )r   r   )r;   tr&   r&   r'   re   T  s    z2SeqBase.find_linear_recurrence.<locals>.<listcomp>N   rH   rG   )Zsympy.matricesrk   lenminrc   appendZdetr   ZLUsolver   r   )r,   ndZgfvarrk   xZlxrZcoeffsll2Zmlistkmyr<   r=   r&   r&   r'   find_linear_recurrence1  sL   "
2&zSeqBase.find_linear_recurrence)NN)#__name__
__module____qualname____doc__Zis_commutativeZ_op_prioritystaticmethodr(   r.   propertyr2   r)   r    r5   r6   r8   r9   r   rE   rB   rL   rN   rP   rQ   rX   r   rZ   r\   r]   r_   ra   rb   rd   rj   rz   r&   r&   r&   r'   r      sR    








,


r   c                   @   s8   e Zd ZdZedd Zedd Zdd Zdd	 Zd
S )EmptySequencea  Represents an empty sequence.

    The empty sequence is also available as a singleton as
    ``S.EmptySequence``.

    Examples
    ========

    >>> from sympy import EmptySequence, SeqPer
    >>> from sympy.abc import x
    >>> EmptySequence
    EmptySequence
    >>> SeqPer((1, 2), (x, 0, 10)) + EmptySequence
    SeqPer((1, 2), (x, 0, 10))
    >>> SeqPer((1, 2)) * EmptySequence
    EmptySequence
    >>> EmptySequence.coeff_mul(-1)
    EmptySequence
    c                 C      t jS rY   )r   EmptySetr1   r&   r&   r'   r)        zEmptySequence.intervalc                 C   r   rY   )r   ZZeror1   r&   r&   r'   r6     r   zEmptySequence.lengthc                 C   s   | S )"See docstring of SeqBase.coeff_mulr&   )r,   rE   r&   r&   r'   rQ     s   zEmptySequence.coeff_mulc                 C   s   t g S rY   )iterr1   r&   r&   r'   rd     s   zEmptySequence.__iter__N)	r{   r|   r}   r~   r   r)   r6   rQ   rd   r&   r&   r&   r'   r   |  s    

r   )	metaclassc                   @   X   e Zd Z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S )SeqExpra  Sequence expression class.

    Various sequences should inherit from this class.

    Examples
    ========

    >>> from sympy.series.sequences import SeqExpr
    >>> from sympy.abc import x
    >>> s = SeqExpr((1, 2, 3), (x, 0, 10))
    >>> s.gen
    (1, 2, 3)
    >>> s.interval
    Interval(0, 10)
    >>> s.length
    11

    See Also
    ========

    sympy.series.sequences.SeqPer
    sympy.series.sequences.SeqFormula
    c                 C   
   | j d S Nr   r?   r1   r&   r&   r'   r2     r^   zSeqExpr.genc                 C   s   t | jd d | jd d S )NrH   rm   )r   r@   r1   r&   r&   r'   r)     s   zSeqExpr.intervalc                 C      | j jS rY   r)   r*   r1   r&   r&   r'   r      r[   zSeqExpr.startc                 C   r   rY   r)   r+   r1   r&   r&   r'   r5     r[   zSeqExpr.stopc                 C      | j | j d S NrH   r5   r    r1   r&   r&   r'   r6        zSeqExpr.lengthc                 C   s   | j d d fS )NrH   r   r?   r1   r&   r&   r'   r8     r   zSeqExpr.variablesN)r{   r|   r}   r~   r   r2   r)   r    r5   r6   r8   r&   r&   r&   r'   r     s    




r   c                   @   sR   e Zd ZdZdddZedd Zedd Zd	d
 Zdd Z	dd Z
dd ZdS )SeqPera  
    Represents a periodic sequence.

    The elements are repeated after a given period.

    Examples
    ========

    >>> from sympy import SeqPer, oo
    >>> from sympy.abc import k

    >>> s = SeqPer((1, 2, 3), (0, 5))
    >>> s.periodical
    (1, 2, 3)
    >>> s.period
    3

    For value at a particular point

    >>> s.coeff(3)
    1

    supports slicing

    >>> s[:]
    [1, 2, 3, 1, 2, 3]

    iterable

    >>> list(s)
    [1, 2, 3, 1, 2, 3]

    sequence starts from negative infinity

    >>> SeqPer((1, 2, 3), (-oo, 0))[0:6]
    [1, 2, 3, 1, 2, 3]

    Periodic formulas

    >>> SeqPer((k, k**2, k**3), (k, 0, oo))[0:6]
    [0, 1, 8, 3, 16, 125]

    See Also
    ========

    sympy.series.sequences.SeqFormula
    Nc                 C   s"  t |}dd }d\}}}|d u r||dtj}}}t|tr;t|dkr-|\}}}nt|dkr;||}|\}}t|ttfrJ|d u sJ|d u rRt	dt
| |tju r`|tju r`t	dt |||f}t|trut tt|}nt	d	| t|d
 |d tju rtjS t| ||S )Nc                 S   s$   | j }t| j dkr| S tdS )NrH   rw   )r9   rn   popr   )
periodicalfreer&   r&   r'   _find_x  s   zSeqPer.__new__.<locals>._find_xNNNr      rm   Invalid limits given: %sz/Both the start and end valuecannot be unboundedz6invalid period %s should be something like e.g (1, 2) rH   )r   r   r$   r   r   rn   rT   r   r   r#   strrI   tupler   r   r   r   r   __new__)clsr   limitsr   rs   r    r5   r&   r&   r'   r     s0   


zSeqPer.__new__c                 C   s
   t | jS rY   )rn   r2   r1   r&   r&   r'   period,  r^   zSeqPer.periodc                 C      | j S rY   r2   r1   r&   r&   r'   r   0  r   zSeqPer.periodicalc                 C   sF   | j tju r| j| | j }n|| j  | j }| j| | jd |S r   )r    r   rI   r5   r   r   subsr8   )r,   rD   idxr&   r&   r'   rB   4  s   zSeqPer._eval_coeffc                 C   s   t |trF| j| j}}|j|j}}t||}g }t|D ]}|||  }	|||  }
||	|
  q| |\}}t|| jd ||fS dS zSee docstring of SeqBase._addr   N	rT   r   r   r   r   rc   rp   r.   r8   r,   r-   Zper1Zlper1Zper2Zlper2Z
per_lengthZnew_perrs   Zele1Zele2r    r5   r&   r&   r'   rN   ;     

zSeqPer._addc                 C   s   t |trF| j| j}}|j|j}}t||}g }t|D ]}|||  }	|||  }
||	|
  q| |\}}t|| jd ||fS dS zSee docstring of SeqBase._mulr   Nr   r   r&   r&   r'   rP   L  r   zSeqPer._mulc                    s,   t    fdd| jD }t|| jd S )r   c                    s   g | ]}|  qS r&   r&   r;   rs   rE   r&   r'   re   `  s    z$SeqPer.coeff_mul.<locals>.<listcomp>rH   )r   r   r   r@   )r,   rE   Zperr&   r   r'   rQ   ]  s   zSeqPer.coeff_mulrY   )r{   r|   r}   r~   r   r   r   r   rB   rN   rP   rQ   r&   r&   r&   r'   r     s    
0(

r   c                   @   sN   e Zd ZdZdddZedd Zdd Zd	d
 Zdd Z	dd Z
dd ZdS )
SeqFormulaaf  
    Represents sequence based on a formula.

    Elements are generated using a formula.

    Examples
    ========

    >>> from sympy import SeqFormula, oo, Symbol
    >>> n = Symbol('n')
    >>> s = SeqFormula(n**2, (n, 0, 5))
    >>> s.formula
    n**2

    For value at a particular point

    >>> s.coeff(3)
    9

    supports slicing

    >>> s[:]
    [0, 1, 4, 9, 16, 25]

    iterable

    >>> list(s)
    [0, 1, 4, 9, 16, 25]

    sequence starts from negative infinity

    >>> SeqFormula(n**2, (-oo, 0))[0:6]
    [0, 1, 4, 9, 16, 25]

    See Also
    ========

    sympy.series.sequences.SeqPer
    Nc                 C   s   t |}dd }d\}}}|d u r||dtj}}}t|tr;t|dkr-|\}}}nt|dkr;||}|\}}t|ttfrJ|d u sJ|d u rRt	dt
| |tju r`|tju r`t	dt |||f}t|d	 |d tju rvtjS t| ||S )
Nc                 S   s2   | j }t|dkr| S |stdS td|  )NrH   rw   z specify dummy variables for %s. If the formula contains more than one free symbol, a dummy variable should be supplied explicitly e.g., SeqFormula(m*n**2, (n, 0, 5)))r9   rn   r   r   r#   )formular   r&   r&   r'   r     s   z#SeqFormula.__new__.<locals>._find_xr   r   r   rm   r   z0Both the start and end value cannot be unboundedrH   )r   r   r$   r   r   rn   rT   r   r   r#   r   rI   r   r   r   r   r   )r   r   r   r   rs   r    r5   r&   r&   r'   r     s&   

zSeqFormula.__new__c                 C   r   rY   r   r1   r&   r&   r'   r     r   zSeqFormula.formulac                 C   s   | j d }| j||S r   )r8   r   r   )r,   rD   rr   r&   r&   r'   rB     s   
zSeqFormula._eval_coeffc           	      C   s`   t |tr.| j| jd }}|j|jd }}|||| }| |\}}t||||fS dS r   rT   r   r   r8   r   r.   	r,   r-   Zform1Zv1Zform2Zv2r   r    r5   r&   r&   r'   rN        
zSeqFormula._addc           	      C   s`   t |tr.| j| jd }}|j|jd }}|||| }| |\}}t||||fS dS r   r   r   r&   r&   r'   rP     r   zSeqFormula._mulc                 C   s"   t |}| j| }t|| jd S )r   rH   )r   r   r   r@   )r,   rE   r   r&   r&   r'   rQ     s   
zSeqFormula.coeff_mulc                 O   s$   t t| jg|R i || jd S r   )r   r   r   r@   )r,   r@   kwargsr&   r&   r'   r     s   $zSeqFormula.expandrY   )r{   r|   r}   r~   r   r   r   rB   rN   rP   rQ   r   r&   r&   r&   r'   r   d  s    
('
		r   c                   @   s   e Zd ZdZd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edd Zedd Zdd Zdd ZdS )RecursiveSeqa  
    A finite degree recursive sequence.

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

    That is, a sequence a(n) that depends on a fixed, finite number of its
    previous values. The general form is

        a(n) = f(a(n - 1), a(n - 2), ..., a(n - d))

    for some fixed, positive integer d, where f is some function defined by a
    SymPy expression.

    Parameters
    ==========

    recurrence : SymPy expression defining recurrence
        This is *not* an equality, only the expression that the nth term is
        equal to. For example, if :code:`a(n) = f(a(n - 1), ..., a(n - d))`,
        then the expression should be :code:`f(a(n - 1), ..., a(n - d))`.

    yn : applied undefined function
        Represents the nth term of the sequence as e.g. :code:`y(n)` where
        :code:`y` is an undefined function and `n` is the sequence index.

    n : symbolic argument
        The name of the variable that the recurrence is in, e.g., :code:`n` if
        the recurrence function is :code:`y(n)`.

    initial : iterable with length equal to the degree of the recurrence
        The initial values of the recurrence.

    start : start value of sequence (inclusive)

    Examples
    ========

    >>> from sympy import Function, symbols
    >>> from sympy.series.sequences import RecursiveSeq
    >>> y = Function("y")
    >>> n = symbols("n")
    >>> fib = RecursiveSeq(y(n - 1) + y(n - 2), y(n), n, [0, 1])

    >>> fib.coeff(3) # Value at a particular point
    2

    >>> fib[:6] # supports slicing
    [0, 1, 1, 2, 3, 5]

    >>> fib.recurrence # inspect recurrence
    Eq(y(n), y(n - 2) + y(n - 1))

    >>> fib.degree # automatically determine degree
    2

    >>> for x in zip(range(10), fib): # supports iteration
    ...     print(x)
    (0, 0)
    (1, 1)
    (2, 1)
    (3, 2)
    (4, 3)
    (5, 5)
    (6, 8)
    (7, 13)
    (8, 21)
    (9, 34)

    See Also
    ========

    sympy.series.sequences.SeqFormula

    Nr   c                    s\  t |tstd|t |tr|jstd||j|fkr%td|jtd|fd}d}|	}|D ]3}	t
|	jdkrEtd|	jd || | }
|
 r\|
jr\|
dk sctd	|	|
 |krk|
 }q8|swd
d t|D }t
||krtdt|}t  tdd |D  }t| |||| } fddt|D |_||_|S )NzErecurrence sequence must be an applied undefined function, found `{}`z0recurrence variable must be a symbol, found `{}`z)recurrence sequence does not match symbolrw   )Zexcluder   rH   z)Recurrence should be in a single variablezDRecurrence should have constant, negative, integer shifts (found {})c                 S   s   g | ]	}t d |qS )zc_{})r   format)r;   rw   r&   r&   r'   re   H      z(RecursiveSeq.__new__.<locals>.<listcomp>z)Number of initial terms must equal degreec                 s   s    | ]}t |V  qd S rY   r   r   r&   r&   r'   	<genexpr>P  s    z'RecursiveSeq.__new__.<locals>.<genexpr>c                    s   i | ]\}} | |qS r&   r&   )r;   rw   Zinitr    ry   r&   r'   
<dictcomp>T  s    z(RecursiveSeq.__new__.<locals>.<dictcomp>)rT   r
   rU   r   r   Z	is_symbolr@   rF   r   findrn   matchZis_constant
is_integerrc   r#   r   r   r   r   	enumeratecachedegree)r   
recurrenceynrq   rJ   r    rw   r   Zprev_ysZprev_yshiftseqr&   r   r'   r   $  sH   


zRecursiveSeq.__new__c                 C   r   zEquation defining recurrence.r   r?   r1   r&   r&   r'   _recurrenceY     
zRecursiveSeq._recurrencec                 C   s   t | j| jd S r   )r   r   r@   r1   r&   r&   r'   r   ^  s   zRecursiveSeq.recurrencec                 C   r   )z*Applied function representing the nth termrH   r?   r1   r&   r&   r'   r   c  r   zRecursiveSeq.ync                 C   r   )z3Undefined function for the nth term of the sequence)r   rF   r1   r&   r&   r'   ry   h  s   zRecursiveSeq.yc                 C   r   )zSequence index symbolrm   r?   r1   r&   r&   r'   rq   m  r   zRecursiveSeq.nc                 C   r   )z"The initial values of the sequencer   r?   r1   r&   r&   r'   rJ   r  r   zRecursiveSeq.initialc                 C   r   )r4      r?   r1   r&   r&   r'   r    w  r   zRecursiveSeq.startc                 C   r   )z&The ending point of the sequence. (oo))r   r$   r1   r&   r&   r'   r5   |  s   zRecursiveSeq.stopc                 C   s   | j tjfS )z&Interval on which sequence is defined.)r    r   r$   r1   r&   r&   r'   r)     r3   zRecursiveSeq.intervalc                 C   s   || j  t| jk r| j| | S tt| j|d D ]}| j | }| j| j|i}|| j}|| j| |< q| j| | j |  S r   )r    rn   r   ry   rc   r   Zxreplacerq   )r,   ri   ZcurrentZ	seq_indexZcurrent_recurrenceZnew_termr&   r&   r'   rB     s   
zRecursiveSeq._eval_coeffc                 c   s     | j }	 | |V  |d7 }q)NTrH   )r    rB   )r,   ri   r&   r&   r'   rd     s   zRecursiveSeq.__iter__r   )r{   r|   r}   r~   r   r   r   r   r   ry   rq   rJ   r    r5   r)   rB   rd   r&   r&   r&   r'   r     s.    
L5








r   Nc                 C   s&   t | } t| trt| |S t| |S )a  
    Returns appropriate sequence object.

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

    If ``seq`` is a sympy sequence, returns :class:`SeqPer` object
    otherwise returns :class:`SeqFormula` object.

    Examples
    ========

    >>> from sympy import sequence
    >>> from sympy.abc import n
    >>> sequence(n**2, (n, 0, 5))
    SeqFormula(n**2, (n, 0, 5))
    >>> sequence((1, 2, 3), (n, 0, 5))
    SeqPer((1, 2, 3), (n, 0, 5))

    See Also
    ========

    sympy.series.sequences.SeqPer
    sympy.series.sequences.SeqFormula
    )r   r   r   r   r   )r   r   r&   r&   r'   sequence  s   


r   c                   @   r   )	SeqExprOpa  
    Base class for operations on sequences.

    Examples
    ========

    >>> from sympy.series.sequences import SeqExprOp, sequence
    >>> from sympy.abc import n
    >>> s1 = sequence(n**2, (n, 0, 10))
    >>> s2 = sequence((1, 2, 3), (n, 5, 10))
    >>> s = SeqExprOp(s1, s2)
    >>> s.gen
    (n**2, (1, 2, 3))
    >>> s.interval
    Interval(5, 10)
    >>> s.length
    6

    See Also
    ========

    sympy.series.sequences.SeqAdd
    sympy.series.sequences.SeqMul
    c                 C   s   t dd | jD S )zjGenerator for the sequence.

        returns a tuple of generators of all the argument sequences.
        c                 s       | ]}|j V  qd S rY   r   r;   ar&   r&   r'   r         z SeqExprOp.gen.<locals>.<genexpr>)r   r@   r1   r&   r&   r'   r2     s   zSeqExprOp.genc                 C   s   t dd | jD  S )zeSequence is defined on the intersection
        of all the intervals of respective sequences
        c                 s   r   rY   r)   r   r&   r&   r'   r     r   z%SeqExprOp.interval.<locals>.<genexpr>)r   r@   r1   r&   r&   r'   r)     s   zSeqExprOp.intervalc                 C   r   rY   r   r1   r&   r&   r'   r      r[   zSeqExprOp.startc                 C   r   rY   r   r1   r&   r&   r'   r5     r[   zSeqExprOp.stopc                 C   s   t tdd | jD S )z%Cumulative of all the bound variablesc                 S   s   g | ]}|j qS r&   )r8   r   r&   r&   r'   re     s    z'SeqExprOp.variables.<locals>.<listcomp>)r   r   r@   r1   r&   r&   r'   r8     s   zSeqExprOp.variablesc                 C   r   r   r   r1   r&   r&   r'   r6     r   zSeqExprOp.lengthN)r{   r|   r}   r~   r   r2   r)   r    r5   r8   r6   r&   r&   r&   r'   r     s    




r   c                   @   ,   e Zd ZdZdd Zedd Zdd ZdS )	rW   a  Represents term-wise addition of sequences.

    Rules:
        * The interval on which sequence is defined is the intersection
          of respective intervals of sequences.
        * Anything + :class:`EmptySequence` remains unchanged.
        * Other rules are defined in ``_add`` methods of sequence classes.

    Examples
    ========

    >>> from sympy import EmptySequence, oo, SeqAdd, SeqPer, SeqFormula
    >>> from sympy.abc import n
    >>> SeqAdd(SeqPer((1, 2), (n, 0, oo)), EmptySequence)
    SeqPer((1, 2), (n, 0, oo))
    >>> SeqAdd(SeqPer((1, 2), (n, 0, 5)), SeqPer((1, 2), (n, 6, 10)))
    EmptySequence
    >>> SeqAdd(SeqPer((1, 2), (n, 0, oo)), SeqFormula(n**2, (n, 0, oo)))
    SeqAdd(SeqFormula(n**2, (n, 0, oo)), SeqPer((1, 2), (n, 0, oo)))
    >>> SeqAdd(SeqFormula(n**3), SeqFormula(n**2))
    SeqFormula(n**3 + n**2, (n, 0, oo))

    See Also
    ========

    sympy.series.sequences.SeqMul
    c                    s   | dtj}t|} fdd  |}dd |D }|s!tjS tdd |D  tju r0tjS |r7t	|S tt
|tj}tj| g|R  S )Nevaluatec                    L   t | trt | trtt | jg S | gS t| r"tt | g S tdNz2Input must be Sequences or  iterables of Sequences)rT   r   rW   summapr@   r   rU   arg_flattenr&   r'   r   !     

z SeqAdd.__new__.<locals>._flattenc                 S   s   g | ]	}|t jur|qS r&   )r   r   r   r&   r&   r'   re   -  r   z"SeqAdd.__new__.<locals>.<listcomp>c                 s   r   rY   r   r   r&   r&   r'   r   3  r   z!SeqAdd.__new__.<locals>.<genexpr>)getr	   r   listr   r   r   r   rW   reducer   r   r(   r   r   r   r@   r   r   r&   r   r'   r     s   

zSeqAdd.__new__c                       d}|r?t | D ]4\} d}t | D ]#\}||krq }|dur5 fdd| D }||  nq|r<|}  nq|st| dkrI|  S t| ddS )a  Simplify :class:`SeqAdd` using known rules.

        Iterates through all pairs and ask the constituent
        sequences if they can simplify themselves with any other constituent.

        Notes
        =====

        adapted from ``Union.reduce``

        TFNc                       g | ]
}| fvr|qS r&   r&   r   srl   r&   r'   re   V  rf   z!SeqAdd.reduce.<locals>.<listcomp>rH   r   )r   rN   rp   rn   r   rW   r@   new_argsZid1Zid2Znew_seqr&   r   r'   r   >  s*   

zSeqAdd.reducec                    s   t  fdd| jD S )z9adds up the coefficients of all the sequences at point ptc                 3   s    | ]}|  V  qd S rY   r   r   rD   r&   r'   r   d  s    z%SeqAdd._eval_coeff.<locals>.<genexpr>)r   r@   rC   r&   r   r'   rB   b  s   zSeqAdd._eval_coeffNr{   r|   r}   r~   r   r   r   rB   r&   r&   r&   r'   rW     s    $
#rW   c                   @   r   )	r`   a'  Represents term-wise multiplication of sequences.

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

    Handles multiplication of sequences only. For multiplication
    with other objects see :func:`SeqBase.coeff_mul`.

    Rules:
        * The interval on which sequence is defined is the intersection
          of respective intervals of sequences.
        * Anything \* :class:`EmptySequence` returns :class:`EmptySequence`.
        * Other rules are defined in ``_mul`` methods of sequence classes.

    Examples
    ========

    >>> from sympy import EmptySequence, oo, SeqMul, SeqPer, SeqFormula
    >>> from sympy.abc import n
    >>> SeqMul(SeqPer((1, 2), (n, 0, oo)), EmptySequence)
    EmptySequence
    >>> SeqMul(SeqPer((1, 2), (n, 0, 5)), SeqPer((1, 2), (n, 6, 10)))
    EmptySequence
    >>> SeqMul(SeqPer((1, 2), (n, 0, oo)), SeqFormula(n**2))
    SeqMul(SeqFormula(n**2, (n, 0, oo)), SeqPer((1, 2), (n, 0, oo)))
    >>> SeqMul(SeqFormula(n**3), SeqFormula(n**2))
    SeqFormula(n**5, (n, 0, oo))

    See Also
    ========

    sympy.series.sequences.SeqAdd
    c                    s   | dtj}t|} fdd  |}|stjS tdd |D  tju r)tjS |r0t	|S tt
|tj}tj| g|R  S )Nr   c                    r   r   )rT   r   r`   r   r   r@   r   rU   r   r   r&   r'   r     r   z SeqMul.__new__.<locals>._flattenc                 s   r   rY   r   r   r&   r&   r'   r     r   z!SeqMul.__new__.<locals>.<genexpr>)r   r	   r   r   r   r   r   r   r`   r   r   r   r(   r   r   r   r&   r   r'   r     s   

zSeqMul.__new__c                    r   )a.  Simplify a :class:`SeqMul` using known rules.

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

        Iterates through all pairs and ask the constituent
        sequences if they can simplify themselves with any other constituent.

        Notes
        =====

        adapted from ``Union.reduce``

        TFNc                    r   r&   r&   r   r   r&   r'   re     rf   z!SeqMul.reduce.<locals>.<listcomp>rH   r   )r   rP   rp   rn   r   r`   r   r&   r   r'   r     s*   

zSeqMul.reducec                 C   s"   d}| j D ]	}|||9 }q|S )z<multiplies the coefficients of all the sequences at point ptrH   )r@   rE   )r,   rD   valr   r&   r&   r'   rB     s   
zSeqMul._eval_coeffNr   r&   r&   r&   r'   r`   g  s    ""
&r`   rY   )7Zsympy.core.basicr   Zsympy.core.cacher   Zsympy.core.compatibilityr   r   r   Zsympy.core.containersr   Zsympy.core.decoratorsr   Zsympy.core.parametersr	   Zsympy.core.functionr
   Zsympy.core.mulr   Zsympy.core.numbersr   Zsympy.core.relationalr   Zsympy.core.singletonr   r   Zsympy.core.symbolr   r   r   Zsympy.core.sympifyr   Zsympy.polysr   r   Zsympy.sets.setsr   r   Zsympy.simplifyr   Zsympy.tensor.indexedr   Zsympy.utilities.iterablesr   Zsympyr   r   r   r   r   r   r   r   r   rW   r`   r&   r&   r&   r'   <module>   sB      c%2 s 
F':j