
    Xh(                         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dS )zRecurrence Operators    )S)Symbolsymbols)sstr)sympifyc                 4    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      l/var/www/tools.fuzzalab.pt/emblema-extractor/venv/lib/python3.11/site-packages/sympy/holonomic/recurrence.pyRecurrenceOperatorsr   	   s!    $ %T955D$%&&    c                   (    e Zd ZdZd Zd ZeZd ZdS )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          | _        d S t          |t                    rt          |d          | _        d S t          |t                    r	|| _        d S d S )NSnF)commutative)
r   RecurrenceOperatorzerooner
   r   
gen_symbol
isinstancestrr   )selfr   r   s      r   __init__z"RecurrenceOperatorAlgebra.__init__;   s    	0Y!4) ) %d>>>DOOO)S)) ,"))"G"G"GIv.. ,"+, ,r   c                 n    dt          | j                  z   dz   | 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?##$&<=Y!!" r   c                 J    | j         |j         k    r| j        |j        k    rdS dS )NTF)r   r   r   others     r   __eq__z RecurrenceOperatorAlgebra.__eq__S   s*    9
""t%:J'J'J45r   N)__name__
__module____qualname____doc__r   r   __repr__r#    r   r   r	   r	      sR         6, , ,   H    r   r	   c                    t          |           t          |          k    r3d t          | |          D             |t          |           d          z   }n2d t          | |          D             | t          |          d          z   }|S )Nc                     g | ]
\  }}||z   S r)   r)   .0abs      r   
<listcomp>z_add_lists.<locals>.<listcomp>\        333Aq1u333r   c                     g | ]
\  }}||z   S r)   r)   r,   s      r   r0   z_add_lists.<locals>.<listcomp>^   r1   r   )lenzip)list1list2sols      r   
_add_listsr8   Z   s    
5zzSZZ33UE!2!2333eCJJKK6HH33UE!2!2333eCJJKK6HHJr   c                   T    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dS )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                    r0| j         j                            t          |                    ||<   Jt          || j         j        j                  s"| j         j                            |          ||<   || _	        t          | j	                  dz
  | _        d S )N   )parentr   list	enumerateintr   
from_sympyr   dtype
listofpolyr3   order)r   list_of_polyr=   ijs        r   r   zRecurrenceOperator.__init__   s      lD)) 	+!,// E E1a%% E&*k&6&A&A!A$$&G&GLOO#At{'7'=>> E&*k&6&A&A!&D&DLO*DO))A-


r   c                    | j         }| j        j        t          |t                    sQt          || j        j        j                  s.| 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                 V     t          |t                    r fd|D             S  |z  gS )Nc                     g | ]}|z  S r)   r)   )r-   rF   r/   s     r   r0   zGRecurrenceOperator.__mul__.<locals>._mul_dmp_diffop.<locals>.<listcomp>   s    333!A333r   )r   r>   )r/   listofothers   ` r   _mul_dmp_diffopz3RecurrenceOperator.__mul__.<locals>._mul_dmp_diffop   s<    +t,, 43333{3333O$$r   r   c                    j         g}t          | t                    rz| D ]v}                    |                              j        d         j        d         t          j        z             }|                    	                    |                     wna|                     j        d         j        d         t          j        z             }|                    	                    |                     |S )Nr   )
r   r   r>   to_sympysubsgensr   OneappendrA   )r/   r7   rF   rG   r   s       r   
_mul_Sni_bz.RecurrenceOperator.__mul__.<locals>._mul_Sni_b   s    9+C!T"" / 3 3Aa((--dilDIaL15<PQQAJJtq1122223
 FF49Q<1)=>>

4??1--...Jr   r<   )rC   r=   r   r   r   rB   rA   r   ranger3   r8   )	r   r"   
listofselfrK   rL   r7   rS   rF   r   s	           @r   __mul__zRecurrenceOperator.__mul__   s    _
{%!344 	+eT[%5%;<< &#{/::75>>JJK  %g*K	% 	% 	%
 ojm[99	 	 	 	 	 q#j//** 	O 	OA$*[11KS//*Q-"M"MNNCC!#t{333r   c                 F   t          t                    st          t                    rt                    t          | j        j        j                  s| j        j                                      fd| j        D             }t          || j                  S d S )Nc                     g | ]}|z  S r)   r)   )r-   rG   r"   s     r   r0   z/RecurrenceOperator.__rmul__.<locals>.<listcomp>   s    666519666r   )	r   r   r@   r   r=   r   rB   rA   rC   )r   r"   r7   s    ` r   __rmul__zRecurrenceOperator.__rmul__   s    %!344 		8%%% !%eT[%5%;<< =)55e<<6666do666C%c4;777		8 		8r   c                    t          |t                    r/t          | j        |j                  }t          || j                  S t          |t
                    rt          |          }| j        }t          || j        j        j                  s!| j        j        	                    |          g}n|g}|d         |d         z   g|dd          z   }t          || j                  S )Nr   r<   )
r   r   r8   rC   r=   r@   r   r   rB   rA   )r   r"   r7   	list_self
list_others        r   __add__zRecurrenceOperator.__add__   s    e/00 	8T_e.>??C%c4;777 %%% !%IeT[%5%;<< % $1==eDDE

#W
Q<*Q-/09QRR=@C%c4;777r   c                     | d|z  z   S Nr)   r!   s     r   __sub__zRecurrenceOperator.__sub__   s    rUl""r   c                     d| z  |z   S r_   r)   r!   s     r   __rsub__zRecurrenceOperator.__rsub__   s    d{U""r   c                 T   |dk    r| S t          | j        j        j        g| j                  }|dk    r|S | j        | j        j        j        k    r=| j        j        j        g|z  | j        j        j        gz   }t          || j                  S | }	 |dz  r||z  }|dz  }|sn||z  }|S )Nr<   r   T   )r   r=   r   r   rC   r
   r   )r   nresultr7   xs        r   __pow__zRecurrenceOperator.__pow__   s    66K#T[%5%9$:DKHH66M?dk8CCC;#()A-1A1E0FFC%c4;777	1u !!GA FA	 r   c                    | j         }d}t          |          D ]\  }}|| j        j        j        k    r| j        j                            |          }|dk    r|dt          |          z   dz   z  }Y|r|dz  }|dk    r|dt          |          z   dz   z  }|dt          |          z   dz   dz   t          |          z   z  }|S )	N r   ()z + r<   z)SnzSn**)rC   r?   r=   r   r   rN   r   )r   rC   	print_strrF   rG   s        r   r   zRecurrenceOperator.__str__  s    _
	j)) 	@ 	@DAqDK$))) ))!,,AAvvS477]S00	 #U"	AvvS477]U22	tAww,v5Q??IIr   c                      t          |t                    r$ j        |j        k    r j        |j        k    rdS dS  j        d         |k    o't	           fd j        dd          D                       S )NTFr   c              3   >   K   | ]}|j         j        j        u V  d S )N)r=   r   r   )r-   rF   r   s     r   	<genexpr>z,RecurrenceOperator.__eq__.<locals>.<genexpr>*  s0      HHqT[%**HHHHHHr   r<   )r   r   rC   r=   allr!   s   ` r   r#   zRecurrenceOperator.__eq__#  s    e/00 	%"222t{el7R7Rtuq!U* IHHHHDOABB4GHHHHH	Ir   N)r$   r%   r&   r'   _op_priorityr   rV   rY   r]   __radd__ra   rc   ri   r   r(   r#   r)   r   r   r   r   b   s        # #J L. . ."04 04 04d
8 
8 
88 8 8& H# # ## # #  (  2 HI I I I Ir   r   c                   ,    e Zd ZdZg fdZd ZeZd ZdS )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         | _	        d S )Nr   FT)

recurrencer   r>   u0r3   _have_init_condr=   r   rP   rf   )r   rx   ry   s      r   r   zHolonomicSequence.__init__4  sl    $"d## 	dDGGDGtw<<1#(D  #'D "',Q/r   c                     d| j                                         dt          | j                  d}| j        s|S d}d}| j        D ],}|dt          |          dt          |          z  }|dz  }-||z   }|S )	NzHolonomicSequence(z, rm   rk   r   z, u(z) = r<   )rx   r(   r   rf   rz   ry   )r   str_solcond_strseq_strrF   r7   s         r   r(   zHolonomicSequence.__repr__A  s     26/1K1K1M1M1M1MtTXTZ||||\# 
	NHGW  d7mmmmT!WWWEE1H$CJr   c                     | j         |j         k    s| j        |j        k    rdS | j        r|j        r| j        |j        k    S dS )NFT)rx   rf   rz   ry   r!   s     r   r#   zHolonomicSequence.__eq__Q  sN    ?e...$&EG2C2C5 	'E$9 	'7eh&&tr   N)r$   r%   r&   r'   r   r(   r   r#   r)   r   r   rv   rv   -  s\          ') 0 0 0 0   G    r   rv   N)r'   sympy.core.singletonr   sympy.core.symbolr   r   sympy.printingr   sympy.core.sympifyr   r   r	   r8   r   rv   r)   r   r   <module>r      s     " " " " " " / / / / / / / /       & & & & & &' ' ',8 8 8 8 8 8 8 8v  HI HI HI HI HI HI HI HIV) ) ) ) ) ) ) ) ) )r   