
    MZd                        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 d dlmZ d d	lmZ d d
lmZ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!m"Z" d dl#m$Z$m%Z% d dl&m'Z' d dl(m)Z)m*Z*m+Z+  G d de      Z, G d de,e      Z- G d de,      Z. G d de.      Z/ G d de.      Z0 G d de,      Z1d(d!Z2 G d" d#e,      Z3 G d$ d%e3      Z4 G d& d'e3      Z5y ))    )Basic)cacheit)Tuple)call_highest_priority)global_parameters)AppliedUndefexpandMul)Integer)Eq)S	Singleton)ordered)DummySymbolWildsympify)Matrix)lcmfactor)IntervalIntersection)Idx)flattenis_sequenceiterablec                   L   e Zd ZdZdZdZed        Zd Ze	d        Z
e	d        Ze	d        Ze	d	        Ze	d
        Ze	d        Ze	d        Zed        Zd Zd Zd Zd Zd Zd Z ed      d        Zd Z ed      d        Zd Zd Z ed      d        Zd Z d Z!d!d Z"y)"SeqBasezBase class for sequencesT   c                 v    	 | j                   }|S # t        t        t        f$ r t        j
                  }Y |S w xY w)z[Return start (if possible) else S.Infinity.

        adapted from Set._infimum_key
        )startNotImplementedErrorAttributeError
ValueErrorr   Infinity)exprr#   s     8/usr/lib/python3/dist-packages/sympy/series/sequences.py
_start_keyzSeqBase._start_key    s@    	JJE  $
, 	JJE	s    $88c                 r    t        | j                  |j                        }|j                  |j                  fS )zTReturns start and stop.

        Takes intersection over the two intervals.
        )r   intervalinfsup)selfotherr,   s      r)   _intersect_intervalzSeqBase._intersect_interval-   s+    
  u~~>||X\\))    c                     t        d| z        )z&Returns the generator for the sequencez(%s).genr$   r/   s    r)   genzSeqBase.gen5   s     "*t"344r2   c                     t        d| z        )z-The interval on which the sequence is definedz(%s).intervalr4   r5   s    r)   r,   zSeqBase.interval:   s     "/D"899r2   c                     t        d| z        ):The starting point of the sequence. This point is includedz
(%s).startr4   r5   s    r)   r#   zSeqBase.start?   s     ","566r2   c                     t        d| z        )z8The ending point of the sequence. This point is includedz	(%s).stopr4   r5   s    r)   stopzSeqBase.stopD   s     "+"455r2   c                     t        d| z        )zLength of the sequencez(%s).lengthr4   r5   s    r)   lengthzSeqBase.lengthI   s     "-$"677r2   c                      y)z-Returns a tuple of variables that are bounded r?   r5   s    r)   	variableszSeqBase.variablesN   s     r2   c                     | j                   D ch c].  }|j                  j                  | j                        D ]  }| 0 c}}S c c}}w )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}
        )argsfree_symbols
differencer@   )r/   ijs      r)   rC   zSeqBase.free_symbolsS   sF     !II 0qq~~Jt~~.0! 0 0 	1 0s   3Ac                     || j                   k  s|| j                  kD  rt        d|d| j                        | j	                  |      S )z#Returns the coefficient at point ptzIndex z out of bounds )r#   r;   
IndexErrorr,   _eval_coeffr/   pts     r)   coeffzSeqBase.coeffd   s>     

?b499nBNOO##r2   c                 2    t        d| j                  z        )NzhThe _eval_coeff method should be added to%s to return coefficient so it is availablewhen coeff calls it.)r$   funcrJ   s     r)   rI   zSeqBase._eval_coeffk   s"    ! #9 %)II#. / 	/r2   c                     | j                   t        j                  u r| j                  }n| j                   }| j                   t        j                  u rd}nd}|||z  z   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   NegativeInfinityr;   )r/   rE   initialsteps       r)   
_ith_pointzSeqBase._ith_pointq   sT    @ ::+++iiGjjG::+++DD4r2   c                      y)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/   r0   s     r)   _addzSeqBase._add        r2   c                      y)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?   rW   s     r)   _mulzSeqBase._mul   rY   r2   c                     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
   rW   s     r)   	coeff_mulzSeqBase.coeff_mul   s    $ 4r2   c                 h    t        |t              st        dt        |      z        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SeqAddrW   s     r)   __add__zSeqBase.__add__   s0     %)84;FGGdE""r2   rd   c                     | |z   S Nr?   rW   s     r)   __radd__zSeqBase.__radd__       e|r2   c                 j    t        |t              st        dt        |      z        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 %sr_   rW   s     r)   __sub__zSeqBase.__sub__   s2     %)=UKLLdUF##r2   rj   c                     |  |z   S rf   r?   rW   s     r)   __rsub__zSeqBase.__rsub__   s    r2   c                 $    | j                  d      S )zNegates the sequence.

        Examples
        ========

        >>> from sympy import SeqFormula
        >>> from sympy.abc import n
        >>> -SeqFormula(n**2)
        SeqFormula(-n**2, (n, 0, oo))
        rP   )r]   r5   s    r)   __neg__zSeqBase.__neg__   s     ~~b!!r2   c                 h    t        |t              st        dt        |      z        t	        | |      S )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)r`   r    ra   rb   SeqMulrW   s     r)   __mul__zSeqBase.__mul__  s0     %)=UKLLdE""r2   rq   c                     | |z  S rf   r?   rW   s     r)   __rmul__zSeqBase.__rmul__  rh   r2   c              #      K   t        | j                        D ]&  }| j                  |      }| j                  |       ( y wrf   )ranger=   rU   rL   )r/   rE   rK   s      r)   __iter__zSeqBase.__iter__  s:     t{{# 	!A#B**R. 	!s   A Ac                 t   t        |t              r"| j                  |      }| j                  |      S t        |t              rq|j
                  |j                  }}|d}|| j                  }t        |||j                  xs d      D cg c]"  }| j                  | j                  |            $ c}S y c c}w )Nr   rQ   )
r`   intrU   rL   slicer#   r;   r=   ru   rT   )r/   indexr#   r;   rE   s        r)   __getitem__zSeqBase.__getitem__#  s    eS!OOE*E::e$$u%++uzz4E}|{{%uzzQ79qDJJtq12 9 9 &9s   
'B5Nc           
         ddl m} | d| D cg c]  } |t        |             }}t        |      }||dz  }nt	        ||dz        }g }	t        d|dz         D ]  }
d|
z  }g }t        |
      D ]  }|j                  ||||
z            t        |      }|j                         dk7  sP ||j                  t        ||
|                   }||k(  rt        |ddd         }	 nag }t        |
||
z
        D ]  }|j                  ||||
z            t        |      }||z  t        ||d       k(  st        |ddd         }	 n ||	S t        |	      }
|
dk(  rg dfS ||
dz
     ||
dz
  z  z  d|	|
dz
     ||
z  z  z
  }}t        |
dz
        D ]Q  }|||   ||z  z  z  }t        |
|z
  dz
        D ]  }||	|   ||   z  |||z   dz   z  z  z  } ||	|   ||dz   z  z  z  }S |	 |t        |      t        |      z        fS c c}w )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   )simplifyN   rQ   rP   )sympy.simplifyr}   r	   lenminru   appendr   detLUsolver   r   )r/   ndgfvarr}   txlxrcoeffsll2mlistkmyrE   rF   s                     r)   find_linear_recurrencezSeqBase.find_linear_recurrence0  sd   D 	,*.r(3QXfQi 33V9AAAb!eAq!A# 	A1BE1X 'Qq1X&'uAuuw!|QYYva"g788$QttW-FqA +ALL1QqS*+5MQ3&23.($QttW-F#	$ =MFAAv4x1veacl*AqsE1H0D,D1qs 0A1eQh&A"1Q3q5\ ;VAYqt^EAaCEN::;51Q3<//A	0
 xq	&)(;<<<M 4s   H)NN)#__name__
__module____qualname____doc__is_commutative_op_prioritystaticmethodr*   r1   propertyr6   r,   r#   r;   r=   r@   rC   r   rL   rI   rU   rX   r[   r]   rd   r   rg   rj   rl   rn   rq   rs   rv   r{   r   r?   r2   r)   r    r       sO   "NL
 
* 5 5 : : 7 7 6 6 8 8   1 1  $ $/* X   (#" 9% &$" 9% &"#$ 9% &!
9I=r2   r    c                   <    e Zd ZdZed        Zed        Zd Zd Zy)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                 "    t         j                  S rf   )r   EmptySetr5   s    r)   r,   zEmptySequence.interval  s    zzr2   c                 "    t         j                  S rf   )r   Zeror5   s    r)   r=   zEmptySequence.length  s    vvr2   c                     | S )"See docstring of SeqBase.coeff_mulr?   )r/   rL   s     r)   r]   zEmptySequence.coeff_mul  s    r2   c                     t        g       S rf   )iterr5   s    r)   rv   zEmptySequence.__iter__  s    Bxr2   N)	r   r   r   r   r   r,   r=   r]   rv   r?   r2   r)   r   r   {  s9    (    r2   r   )	metaclassc                   p    e Zd ZdZed        Zed        Zed        Zed        Zed        Z	ed        Z
y)	SeqExpra  Sequence expression class.

    Various sequences should inherit from this class.

    Examples
    ========

    >>> from sympy.series.sequences import SeqExpr
    >>> from sympy.abc import x
    >>> from sympy import Tuple
    >>> s = SeqExpr(Tuple(1, 2, 3), Tuple(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                      | j                   d   S Nr   rB   r5   s    r)   r6   zSeqExpr.gen  s    yy|r2   c                 Z    t        | j                  d   d   | j                  d   d         S )NrQ   r~   )r   rB   r5   s    r)   r,   zSeqExpr.interval  s'    		!Q1a99r2   c                 .    | j                   j                  S rf   r,   r-   r5   s    r)   r#   zSeqExpr.start      }}   r2   c                 .    | j                   j                  S rf   r,   r.   r5   s    r)   r;   zSeqExpr.stop  r   r2   c                 :    | j                   | j                  z
  dz   S NrQ   r;   r#   r5   s    r)   r=   zSeqExpr.length      yy4::%))r2   c                 (    | j                   d   d   fS )NrQ   r   r   r5   s    r)   r@   zSeqExpr.variables  s    		!Q!!r2   N)r   r   r   r   r   r6   r,   r#   r;   r=   r@   r?   r2   r)   r   r     s    2   : : ! ! ! ! * * " "r2   r   c                   P    e Zd ZdZd
dZed        Zed        Zd Zd Z	d Z
d	 Zy)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                    t        |      }d }d\  }}}| ||      dt        j                  }}}t        |t              r0t        |      dk(  r|\  }}}nt        |      dk(  r ||      }|\  }}t        |t        t        f      r||t        dt        |      z        |t        j                  u r|t        j                  u rt        d      t        |||f      }t        |t              rt        t        t        |                  }nt        d|z        t        |d	   |d         t        j                  u rt        j                   S t#        j$                  | ||      S )
Nc                     | j                   }t        | j                         dk(  r|j                         S t        d      S )NrQ   r   )rC   r   popr   )
periodicalfrees     r)   _find_xzSeqPer.__new__.<locals>._find_x  s6    **D:**+q0xxz!Sz!r2   NNNr      r~   Invalid limits given: %sz/Both the start and end valuecannot be unboundedz6invalid period %s should be something like e.g (1, 2) rQ   )r   r   r'   r   r   r   r`   r   r   r&   strrR   tupler   r   r   r   r   __new__)clsr   limitsr   r   r#   r;   s          r)   r   zSeqPer.__new__  sT   Z(
	" *5$>$Z0!QZZduAvu%6{a!'5$V!J'$t!fc]+u}7#f+EFFA&&&41::+=  "7 8 8 !UD)*z5) wz':!;<J 02<= > > F1Ivay)QZZ7??"}}S*f55r2   c                 ,    t        | j                        S rf   )r   r6   r5   s    r)   periodzSeqPer.period,  s    488}r2   c                     | j                   S rf   r6   r5   s    r)   r   zSeqPer.periodical0      xxr2   c                    | j                   t        j                  u r| j                  |z
  | j                  z  }n|| j                   z
  | j                  z  }| j
                  |   j                  | j                  d   |      S r   )r#   r   rR   r;   r   r   subsr@   )r/   rK   idxs      r)   rI   zSeqPer._eval_coeff4  se    ::+++99r>T[[0C

?dkk1Cs#(():B??r2   c                 h   t        |t              r| j                  | j                  }}|j                  |j                  }}t	        ||      }g }t        |      D ]&  }|||z     }	|||z     }
|j                  |	|
z          ( | j                  |      \  }}t        || j                  d   ||f      S yzSee docstring of SeqBase._addr   N	r`   r   r   r   r   ru   r   r1   r@   r/   r0   per1lper1per2lper2
per_lengthnew_perr   ele1ele2r#   r;   s                r)   rX   zSeqPer._add;      eV$//4;;%D**ELL%DUE*JG:& ,AIAItd{+,
 2259KE4'DNN1$5ud#CDD %r2   c                 h   t        |t              r| j                  | j                  }}|j                  |j                  }}t	        ||      }g }t        |      D ]&  }|||z     }	|||z     }
|j                  |	|
z         ( | j                  |      \  }}t        || j                  d   ||f      S yzSee docstring of SeqBase._mulr   Nr   r   s                r)   r[   zSeqPer._mulL  r   r2   c                     t        |      }| j                  D cg c]  }||z  	 }}t        || j                  d         S c c}w r   rQ   )r   r   r   rB   )r/   rL   r   pers       r)   r]   zSeqPer.coeff_mul]  s@    "&//2Qq5y22c499Q<(( 3s   Arf   )r   r   r   r   r   r   r   r   rI   rX   r[   r]   r?   r2   r)   r   r     sM    .`&6P    @E"E")r2   r   c                   F    e Zd ZdZd
dZed        Zd Zd Zd Z	d Z
d	 Zy)
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                 P   t        |      }d }d\  }}}| ||      dt        j                  }}}t        |t              r0t        |      dk(  r|\  }}}nt        |      dk(  r ||      }|\  }}t        |t        t        f      r||t        dt        |      z        |t        j                  u r|t        j                  u rt        d      t        |||f      }t        |d   |d         t        j                  u rt        j                  S t        j                   | ||      S )	Nc                     | j                   }t        |      dk(  r|j                         S |st        d      S t	        d| z        )NrQ   r   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)))rC   r   r   r   r&   )formular   s     r)   r   z#SeqFormula.__new__.<locals>._find_x  sN    ''D4yA~xxz!Sz! O  r2   r   r   r   r~   r   z0Both the start and end value cannot be unboundedrQ   )r   r   r'   r   r   r   r`   r   r   r&   r   rR   r   r   r   r   r   )r   r   r   r   r   r#   r;   s          r)   r   zSeqFormula.__new__  s   '"	 *5$>$W-q!**duAvu%6{a!'5$V!G$$t!fc]+u}7#f+EFFA&&&41::+=  "7 8 8!UD)*F1Ivay)QZZ7??"}}S'622r2   c                     | j                   S rf   r   r5   s    r)   r   zSeqFormula.formula  r   r2   c                 X    | j                   d   }| j                  j                  ||      S r   )r@   r   r   )r/   rK   r   s      r)   rI   zSeqFormula._eval_coeff  s'    NN1||  B''r2   c                     t        |t              rn| j                  | j                  d   }}|j                  |j                  d   }}||j	                  ||      z   }| j                  |      \  }}t        ||||f      S yr   r`   r   r   r@   r   r1   	r/   r0   form1v1form2v2r   r#   r;   s	            r)   rX   zSeqFormula._add  z    eZ(dnnQ&72Euq'92EejjR00G2259KE4gE4'899 )r2   c                     t        |t              rn| j                  | j                  d   }}|j                  |j                  d   }}||j	                  ||      z  }| j                  |      \  }}t        ||||f      S yr   r   r   s	            r)   r[   zSeqFormula._mul  r   r2   c                 h    t        |      }| j                  |z  }t        || j                  d         S r   )r   r   r   rB   )r/   rL   r   s      r)   r]   zSeqFormula.coeff_mul  s.    ,,&'499Q<00r2   c                 b    t        t        | j                  g|i || j                  d         S r   )r   r	   r   rB   )r/   rB   kwargss      r)   r	   zSeqFormula.expand  s*    &???1NNr2   rf   )r   r   r   r   r   r   r   rI   rX   r[   r]   r	   r?   r2   r)   r   r   d  s<    &P%3N  (::1Or2   r   c                       e Zd ZdZddZed        Zed        Zed        Zed        Z	ed        Z
ed	        Zed
        Zed        Zed        Zd Zd Zy)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

    Nc                    t        |t              st        dj                  |            t        |t              r|j
                  st        dj                  |            |j                  |fk7  rt        d      |j                  }t        d|f      }d}|j                  |      }	|	D ]  }
t        |
j                        dk7  rt        d      |
j                  d   j                  ||z         |   }|j                         r|j                  r|dk  st        d	j                  |
            | |kD  s| } |s0t        |      D cg c]  }t        d
j                  |             }}t        |      |k7  rt!        d      t#        |      }t%        |      }t'        d |D         }t	        j(                  | |||||      }t+        |      D ci c]  \  }} |||z         | c}}|_        ||_        |S c c}w c c}}w )NzErecurrence sequence must be an applied undefined function, found `{}`z0recurrence variable must be a symbol, found `{}`z)recurrence sequence does not match symbolr   )excluder   rQ   z)Recurrence should be in a single variablezDRecurrence should have constant, negative, integer shifts (found {})zc_{}z)Number of initial terms must equal degreec              3   2   K   | ]  }t        |        y wrf   r   ).0r   s     r)   	<genexpr>z'RecursiveSeq.__new__.<locals>.<genexpr>P  s     6'!*6s   )r`   r   ra   formatr   	is_symbolrB   rN   r   findr   matchis_constant
is_integerru   r   r&   r   r   r   r   	enumeratecachedegree)r   
recurrenceynr   rS   r#   r   r   r  prev_ysprev_yshiftseqinits                 r)   r   zRecursiveSeq.__new__$  s   "l+ ++16":7 7 !U#1;; ++16!96 6 77qd?GHHGGqd# //!$ 	 F6;;1$ KLLKKN((Q/2E%%'E,<,< !..4fVn> > v	  8=fF1uV]]1-.FGFw<6!HII6g67mmCRGUC7@7IJGAtQuqy\4'J	

 G Ks   !G<Hc                      | j                   d   S zEquation defining recurrence.r   r   r5   s    r)   _recurrencezRecursiveSeq._recurrenceY       yy|r2   c                 H    t        | j                  | j                  d         S r  )r   r  rB   r5   s    r)   r  zRecursiveSeq.recurrence^  s     $''499Q<((r2   c                      | j                   d   S )z*Applied function representing the nth termrQ   r   r5   s    r)   r  zRecursiveSeq.ync  r  r2   c                 .    | j                   j                  S )z3Undefined function for the nth term of the sequence)r  rN   r5   s    r)   r   zRecursiveSeq.yh  s     ww||r2   c                      | j                   d   S )zSequence index symbolr~   r   r5   s    r)   r   zRecursiveSeq.nm  r  r2   c                      | j                   d   S )z"The initial values of the sequencer   r   r5   s    r)   rS   zRecursiveSeq.initialr  r  r2   c                      | j                   d   S )r9      r   r5   s    r)   r#   zRecursiveSeq.startw  r  r2   c                 "    t         j                  S )z&The ending point of the sequence. (oo))r   r'   r5   s    r)   r;   zRecursiveSeq.stop|  s     zzr2   c                 :    | j                   t        j                  fS )z&Interval on which sequence is defined.)r#   r   r'   r5   s    r)   r,   zRecursiveSeq.interval  s     

AJJ''r2   c                 
   || j                   z
  t        | j                        k  r| j                  | j                  |         S t	        t        | j                        |dz         D ]q  }| j                   |z   }| j
                  j                  | j                  |i      }|j                  | j                        }|| j                  | j                  |      <   s | j                  | j                  | j                   z            S r   )r#   r   r  r   ru   r  xreplacer   )r/   rz   current	seq_indexcurrent_recurrencenew_terms         r)   rI   zRecursiveSeq._eval_coeff  s    4::DJJ/::dffUm,,S_eai8 	5G 

W,I!%!1!1!:!:DFFI;N!O)224::>H,4DJJtvvi()	5 zz$&&g!5677r2   c              #   V   K   | j                   }	 | j                  |       |dz  }wr   )r#   rI   )r/   rz   s     r)   rv   zRecursiveSeq.__iter__  s1     

""5))QJE s   ')r   )r   r   r   r   r   r   r  r  r  r   r   rS   r#   r;   r,   rI   rv   r?   r2   r)   r   r     s    JX3j   ) )             ( (8r2   r   Nc                 h    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   s     r)   sequencer     s1    4 #,C3c6""#v&&r2   c                   p    e Zd ZdZed        Zed        Zed        Zed        Zed        Z	ed        Z
y)		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                 :    t        d | j                  D              S )zjGenerator for the sequence.

        returns a tuple of generators of all the argument sequences.
        c              3   4   K   | ]  }|j                     y wrf   r   r   as     r)   r   z SeqExprOp.gen.<locals>.<genexpr>  s     .qQUU.   )r   rB   r5   s    r)   r6   zSeqExprOp.gen  s     .DII...r2   c                 4    t        d | j                  D         S )zeSequence is defined on the intersection
        of all the intervals of respective sequences
        c              3   4   K   | ]  }|j                     y wrf   r,   r%  s     r)   r   z%SeqExprOp.interval.<locals>.<genexpr>  s     <Qajj<r'  )r   rB   r5   s    r)   r,   zSeqExprOp.interval  s    
 <$))<==r2   c                 .    | j                   j                  S rf   r   r5   s    r)   r#   zSeqExprOp.start  r   r2   c                 .    | j                   j                  S rf   r   r5   s    r)   r;   zSeqExprOp.stop  r   r2   c                 x    t        t        | j                  D cg c]  }|j                   c}            S c c}w )z%Cumulative of all the bound variables)r   r   rB   r@   )r/   r&  s     r)   r@   zSeqExprOp.variables  s*     W499=aakk=>??=s   7c                 :    | j                   | j                  z
  dz   S r   r   r5   s    r)   r=   zSeqExprOp.length  r   r2   N)r   r   r   r   r   r6   r,   r#   r;   r@   r=   r?   r2   r)   r"  r"    s    0 / / > > ! ! ! ! @ @ * *r2   r"  c                   ,    e Zd ZdZd Zed        Zd Zy)rc   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                    |j                  dt        j                        }t        |      }fd |      }|D cg c]  }|t        j
                  us| }}|st        j
                  S t        d |D         t        j                  u rt        j
                  S |rt        j                  |      S t        t        |t        j                              }t        j                  | g| S c c}w )Nevaluatec                     t        | t              r3t        | 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)r`   r    rc   summaprB   r   ra   arg_flattens    r)   r8  z SeqAdd.__new__.<locals>._flatten!  sc    #w'c6*s8SXX6;;5L}3x-r22 6 7 7r2   c              3   4   K   | ]  }|j                     y wrf   r*  r%  s     r)   r   z!SeqAdd.__new__.<locals>.<genexpr>3       3!**3r'  )getr   r1  listr   r   r   r   rc   reducer   r    r*   r   r   )r   rB   r   r1  r&  r8  s        @r)   r   zSeqAdd.__new__  s    ::j*;*D*DE Dz		7 ~<a1AOO#;<< ??"3d34

B??" ==&&GD'"4"456}}S(4(( =s   C-C-c                 P   d}|rst        |       D ]b  \  }}d}t        |       D ]G  \  }}||k(  r|j                  |      }| | D cg c]  }|||fvs
| }}|j                  |        n |s`|}  n |rst        |       dk(  r| j	                         S t        | d      S c c}w )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``

        TFrQ   r1  )r  rX   r   r   r   rc   rB   new_argsid1sid2r   new_seqr&  s           r)   r=  zSeqAdd.reduce>  s     #D/ Q 'o 	FCcz ffQiG */3#G!qAA#G#G 0	 #D " t9>88:$// $H   B#B#c                 @    t        fd| j                  D              S )z9adds up the coefficients of all the sequences at point ptc              3   @   K   | ]  }|j                          y wrf   )rL   )r   r&  rK   s     r)   r   z%SeqAdd._eval_coeff.<locals>.<genexpr>d  s     211772;2s   )r4  rB   rJ   s    `r)   rI   zSeqAdd._eval_coeffb  s    2		222r2   Nr   r   r   r   r   r   r=  rI   r?   r2   r)   rc   rc     s'    8")H !0 !0F3r2   rc   c                   ,    e Zd ZdZd Zed        Zd Zy)rp   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                    |j                  dt        j                        }t        |      }fd |      }|st        j
                  S t        d |D         t        j                  u rt        j
                  S |rt        j                  |      S t        t        |t        j                              }t        j                  | g| S )Nr1  c                     t        | t              r3t        | t              r t        t	        | j
                        g       S | gS t        |       rt        t	        |       g       S t        d      r3  )r`   r    rp   r4  r5  rB   r   ra   r6  s    r)   r8  z SeqMul.__new__.<locals>._flatten  sc    #w'c6*s8SXX6;;5L#3x-r22 6 7 7r2   c              3   4   K   | ]  }|j                     y wrf   r*  r%  s     r)   r   z!SeqMul.__new__.<locals>.<genexpr>  r:  r'  )r;  r   r1  r<  r   r   r   r   rp   r=  r   r    r*   r   r   )r   rB   r   r1  r8  s       @r)   r   zSeqMul.__new__  s    ::j*;*D*DE Dz		7 ~ ??"3d34

B??" ==&&GD'"4"456}}S(4((r2   c                 P   d}|rst        |       D ]b  \  }}d}t        |       D ]G  \  }}||k(  r|j                  |      }| | D cg c]  }|||fvs
| }}|j                  |        n |s`|}  n |rst        |       dk(  r| j	                         S t        | d      S c c}w )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``

        TFrQ   r?  )r  r[   r   r   r   rp   r@  s           r)   r=  zSeqMul.reduce  s      #D/ Q 'o 	FCcz ffQiG */3#G!qAA#G#G 0	 #D " t9>88:$// $HrF  c                 T    d}| j                   D ]  }||j                  |      z  } |S )z<multiplies the coefficients of all the sequences at point ptrQ   )rB   rL   )r/   rK   valr&  s       r)   rI   zSeqMul._eval_coeff  s1     	A1772;C	
r2   NrI  r?   r2   r)   rp   rp   g  s(     D )D $0 $0Lr2   rp   rf   )6sympy.core.basicr   sympy.core.cacher   sympy.core.containersr   sympy.core.decoratorsr   sympy.core.parametersr   sympy.core.functionr   r	   sympy.core.mulr   sympy.core.numbersr   sympy.core.relationalr   sympy.core.singletonr   r   sympy.core.sortingr   sympy.core.symbolr   r   r   sympy.core.sympifyr   sympy.matricesr   sympy.polysr   r   sympy.sets.setsr   r   sympy.tensor.indexedr   sympy.utilities.iterablesr   r   r   r    r   r   r   r   r   r   r"  rc   rp   r?   r2   r)   <module>rc     s    " $ ' 7 3 4  & $ - & 1 1 & ! # 2 $ D D_=e _=B"Gy "J0"g 0"fN)W N)bqO qOfB7 BJ'N7* 7*tg3Y g3TqY qr2   