
    MZd*                         d Z ddlmZ ddlmZmZ ddlmZ ddlm	Z	 d Z
 G d d      Zd	 Z G d
 d      Z G d d      Zy)zRecurrence Operators    )S)Symbolsymbols)sstr)sympifyc                 6    t        | |      }||j                  fS )a+  
    Returns an Algebra of Recurrence Operators and the operator for
    shifting i.e. the `Sn` operator.
    The first argument needs to be the base polynomial ring for the algebra
    and the second argument must be a generator which can be either a
    noncommutative Symbol or a string.

    Examples
    ========

    >>> from sympy import ZZ
    >>> from sympy import symbols
    >>> from sympy.holonomic.recurrence import RecurrenceOperators
    >>> n = symbols('n', integer=True)
    >>> R, Sn = RecurrenceOperators(ZZ.old_poly_ring(n), 'Sn')
    )RecurrenceOperatorAlgebrashift_operator)base	generatorrings      </usr/lib/python3/dist-packages/sympy/holonomic/recurrence.pyRecurrenceOperatorsr   	   s!    $ %T95D$%%&&    c                   &    e Zd ZdZd Zd ZeZd Zy)r	   a  
    A Recurrence Operator Algebra is a set of noncommutative polynomials
    in intermediate `Sn` and coefficients in a base ring A. It follows the
    commutation rule:
    Sn * a(n) = a(n + 1) * Sn

    This class represents a Recurrence Operator Algebra and serves as the parent ring
    for Recurrence Operators.

    Examples
    ========

    >>> from sympy import ZZ
    >>> from sympy import symbols
    >>> from sympy.holonomic.recurrence import RecurrenceOperators
    >>> n = symbols('n', integer=True)
    >>> R, Sn = RecurrenceOperators(ZZ.old_poly_ring(n), 'Sn')
    >>> R
    Univariate Recurrence Operator Algebra in intermediate Sn over the base ring
    ZZ[n]

    See Also
    ========

    RecurrenceOperator
    c                     || _         t        |j                  |j                  g|       | _        |t        dd      | _        y t        |t              rt        |d      | _        y t        |t              r|| _        y y )NSnF)commutative)
r   RecurrenceOperatorzerooner
   r   
gen_symbol
isinstancestrr   )selfr   r   s      r   __init__z"RecurrenceOperatorAlgebra.__init__;   sl    	0YY!4) %d>DO)S)"))"GIv."+ /r   c                 r    dt        | j                        z   dz   | j                  j                         z   }|S )Nz7Univariate Recurrence Operator Algebra in intermediate z over the base ring )r   r   r   __str__)r   strings     r   r   z!RecurrenceOperatorAlgebra.__str__J   s<    J4??#$&<=YY!" r   c                 j    | j                   |j                   k(  r| j                  |j                  k(  ryyNTF)r   r   r   others     r   __eq__z RecurrenceOperatorAlgebra.__eq__S   s)    99

"t%:J:J'Jr   N)__name__
__module____qualname____doc__r   r   __repr__r$    r   r   r	   r	      s    6, Hr   r	   c                    t        |       t        |      k  r3t        | |      D cg c]
  \  }}||z    c}}|t        |       d  z   }|S t        | |      D cg c]
  \  }}||z    c}}| t        |      d  z   }|S c c}}w c c}}w N)lenzip)list1list2absols        r   
_add_listsr4   Z   s    
5zSZ!$UE!23Aq1u3eCJK6HH J "%UE!23Aq1u3eCJK6HHJ 43s   A>Bc                   R    e Zd ZdZdZd Zd Zd Zd ZeZ	d Z
d Zd	 Zd
 ZeZd Zy)r   a  
    The Recurrence Operators are defined by a list of polynomials
    in the base ring and the parent ring of the Operator.

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

    Takes a list of polynomials for each power of Sn and the
    parent ring which must be an instance of RecurrenceOperatorAlgebra.

    A Recurrence Operator can be created easily using
    the operator `Sn`. See examples below.

    Examples
    ========

    >>> from sympy.holonomic.recurrence import RecurrenceOperator, RecurrenceOperators
    >>> from sympy import ZZ
    >>> from sympy import symbols
    >>> n = symbols('n', integer=True)
    >>> R, Sn = RecurrenceOperators(ZZ.old_poly_ring(n),'Sn')

    >>> RecurrenceOperator([0, 1, n**2], R)
    (1)Sn + (n**2)Sn**2

    >>> Sn*n
    (n + 1)Sn

    >>> n*Sn*n + 1 - Sn**2*n
    (1) + (n**2 + n)Sn + (-n - 2)Sn**2

    See Also
    ========

    DifferentialOperatorAlgebra
       c                    || _         t        |t              rt        |      D ]  \  }}t        |t              r2| j                   j
                  j                  t        |            ||<   Ht        || j                   j
                  j                        rs| j                   j
                  j                  |      ||<    || _	        t        | j                        dz
  | _        y )N   )parentr   list	enumerateintr   
from_sympyr   dtype
listofpolyr-   order)r   list_of_polyr9   ijs        r   r   zRecurrenceOperator.__init__   s      lD)!,/ E1a%&*kk&6&6&A&A!A$&GLO#At{{'7'7'='=>&*kk&6&6&A&A!&DLO	E +DO)A-
r   c                     | j                   }| j                  j                  t        |t              s^t        || j                  j                  j
                        s0| j                  j                  j                  t        |            g}n|g}n|j                   }d } ||d   |      }fd}t        dt        |            D ]   } ||      }t        | |||   |            }" t	        || j                        S )z
        Multiplies two Operators and returns another
        RecurrenceOperator instance using the commutation rule
        Sn * a(n) = a(n + 1) * Sn
        c                 l    t        |t              rg }|D ]  }|j                  || z          |S | |z  gS r,   )r   r:   append)r2   listofotherr3   rB   s       r   _mul_dmp_diffopz3RecurrenceOperator.__mul__.<locals>._mul_dmp_diffop   sB    +t,$ &AJJq1u%&
K((r   r   c                    j                   g}t        | t              ru| D ]n  }j                  |      j	                  j
                  d   j
                  d   t        j                  z         }|j                  j                  |             p |S | j	                  j
                  d   j
                  d   t        j                  z         }|j                  j                  |             |S )Nr   )
r   r   r:   to_sympysubsgensr   OnerF   r=   )r2   r3   rB   rC   r   s       r   
_mul_Sni_bz.RecurrenceOperator.__mul__.<locals>._mul_Sni_b   s    99+C!T" 3Aa(--diilDIIaL155<PQAJJtq123 J FF499Q<1)=>

4??1-.Jr   r8   )r?   r9   r   r   r   r>   r=   r   ranger-   r4   )	r   r#   
listofselfrG   rH   r3   rN   rB   r   s	           @r   __mul__zRecurrenceOperator.__mul__   s     __
{{%!34eT[[%5%5%;%;<#{{//::75>JK  %g**K	) jm[9	 q#j/* 	OA$[1KS/*Q-"MNC		O "#t{{33r   c                 r   t        |t              st        |t              rt        |      }t        || j                  j
                  j                        s%| j                  j
                  j                  |      }g }| j                  D ]  }|j                  ||z          t        || j                        S y r,   )
r   r   r<   r   r9   r   r>   r=   r?   rF   )r   r#   r3   rC   s       r   __rmul__zRecurrenceOperator.__rmul__   s    %!34%%%eT[[%5%5%;%;<))55e<C__ &

519%& &c4;;77 5r   c                    t        |t              r6t        | j                  |j                        }t        || j                        S t        |t
              rt        |      }| j                  }t        || j                  j                  j                        s'| j                  j                  j                  |      g}n|g}g }|j                  |d   |d   z          ||dd  z  }t        || j                        S )Nr   r8   )r   r   r4   r?   r9   r<   r   r   r>   r=   rF   )r   r#   r3   	list_self
list_others        r   __add__zRecurrenceOperator.__add__   s    e/0T__e.>.>?C%c4;;77 %%%IeT[[%5%5%;%;< $11==eDE
#W
CJJy|jm349QR= C%c4;;77r   c                     | d|z  z   S Nr*   r"   s     r   __sub__zRecurrenceOperator.__sub__   s    rUl""r   c                     d| z  |z   S rY   r*   r"   s     r   __rsub__zRecurrenceOperator.__rsub__   s    d{U""r   c                 B   |dk(  r| S |dk(  r5t        | j                  j                  j                  g| j                        S | j                  | j                  j
                  j                  k(  rg }t        d|      D ]1  }|j                  | j                  j                  j                         3 |j                  | j                  j                  j                         t        || j                        S |dz  dk(  r| |dz
  z  }|| z  S |dz  dk(  r| |dz  z  }||z  S y )Nr8   r      )	r   r9   r   r   r?   r
   rO   rF   r   )r   nr3   rB   	powreduces        r   __pow__zRecurrenceOperator.__pow__   s   6K6%t{{'7'7';';&<dkkJJ??dkk88CCCC1a[ 2

4;;++0012JJt{{''++,%c4;;77 1uz 1q5M	 4''Q! 1q5M	 9,, r   c                 L   | j                   }d}t        |      D ]  \  }}|| j                  j                  j                  k(  r*|dk(  r|dt        |      z   dz   z  }D|r|dz  }|dk(  r|dt        |      z   dz   z  }e|dt        |      z   dz   dz   t        |      z   z  } |S )	N r   ()z + r8   z)SnzSn**)r?   r;   r9   r   r   r   )r   r?   	print_strrB   rC   s        r   r   zRecurrenceOperator.__str__  s    __
	j) 	@DAqDKK$$)))AvS47]S00	U"	AvS47]U22	tAw,v5Q??I	@" r   c                 "   t        |t              r4| j                  |j                  k(  r| j                  |j                  k(  ryy| j                  d   |k(  r9| j                  dd  D ]&  }|| j                  j                  j
                  us& y yy)NTFr   r8   )r   r   r?   r9   r   r   )r   r#   rB   s      r   r$   zRecurrenceOperator.__eq__,  s    e/0%"2"22t{{ell7Rq!U*, %A 0 0 5 55$% r   N)r%   r&   r'   r(   _op_priorityr   rQ   rS   rW   __radd__r[   r]   rb   r   r)   r$   r*   r   r   r   r   b   sK    #J L."44l88* H##-,. Hr   r   c                   *    e Zd ZdZg fdZd ZeZd Zy)HolonomicSequencez
    A Holonomic Sequence is a type of sequence satisfying a linear homogeneous
    recurrence relation with Polynomial coefficients. Alternatively, A sequence
    is Holonomic if and only if its generating function is a Holonomic Function.
    c                     || _         t        |t              s	|g| _        n|| _        t	        | j                        dk(  rd| _        nd| _        |j                  j                  j                  d   | _	        y )Nr   FT)

recurrencer   r:   u0r-   _have_init_condr9   r   rL   r`   )r   rn   ro   s      r   r   zHolonomicSequence.__init__C  sa    $"d#dDGDGtww<1#(D #'D ""'',,Q/r   c                    d| j                   j                         dt        | j                        d}| j                  s|S d}d}| j
                  D ]$  }|dt        |      dt        |      z  }|dz  }& ||z   }|S )	NzHolonomicSequence(z, rf   rd   r   z, u(z) = r8   )rn   r)   r   r`   rp   ro   )r   str_solcond_strseq_strrB   r3   s         r   r)   zHolonomicSequence.__repr__P  s    26//1K1K1MtTXTZTZ|\##NHGWW d7mT!WEE1 H$CJr   c                     | j                   |j                   k(  rN| j                  |j                  k(  r4| j                  r'|j                  r| j                  |j                  k(  ryyyyyr!   )rn   r`   rp   ro   r"   s     r   r$   zHolonomicSequence.__eq__`  sT    ??e...vv ''E,A,Aww%((*#$r   N)r%   r&   r'   r(   r   r)   r   r$   r*   r   r   rl   rl   <  s"     ') 0 Gr   rl   N)r(   sympy.core.singletonr   sympy.core.symbolr   r   sympy.printingr   sympy.core.sympifyr   r   r	   r4   r   rl   r*   r   r   <module>rz      s@     " /  &',8 8vW Wt1 1r   