U
    ZÊ¹j±*  ã                   @   sv   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d„ Z
G dd	„ d	ƒZd
d„ ZG dd„ dƒZG dd„ dƒZdS )zRecurrence Operatorsé    )ÚS)ÚSymbolÚsymbols)Ússtr)Úsympifyc                 C   s   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Úring© r   úY/var/www/html/bwave/python/venv/lib/python3.8/site-packages/sympy/holonomic/recurrence.pyÚRecurrenceOperators	   s    
r   c                   @   s,   e Zd ZdZdd„ Zdd„ ZeZd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                 C   s`   || _ t|j|jg| ƒ| _|d kr2tddd�| _n*t|tƒrLt|dd�| _nt|t	ƒr\|| _d S )NZSnF)Zcommutative)
r	   ÚRecurrenceOperatorÚzeroÚoner   r   Ú
gen_symbolÚ
isinstanceÚstrr   )Úselfr	   r
   r   r   r   Ú__init__;   s    
 ÿ

z"RecurrenceOperatorAlgebra.__init__c                 C   s    dt | jƒ d | j ¡  }|S )Nz7Univariate Recurrence Operator Algebra in intermediate z over the base ring )r   r   r	   Ú__str__)r   Ústringr   r   r   r   J   s    ÿÿþz!RecurrenceOperatorAlgebra.__str__c                 C   s$   | j |j kr| j|jkrdS dS d S ©NTF)r	   r   ©r   Úotherr   r   r   Ú__eq__S   s    z RecurrenceOperatorAlgebra.__eq__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   Ú__repr__r   r   r   r   r   r      s
   r   c                 C   s^   t | ƒt |ƒkr6dd„ t| |ƒD ƒ|t | ƒd …  }n$dd„ t| |ƒD ƒ| t |ƒd …  }|S )Nc                 S   s   g | ]\}}|| ‘qS r   r   ©Ú.0ÚaÚbr   r   r   Ú
<listcomp>\   s     z_add_lists.<locals>.<listcomp>c                 S   s   g | ]\}}|| ‘qS r   r   r"   r   r   r   r&   ^   s     )ÚlenÚzip)Zlist1Zlist2Úsolr   r   r   Ú
_add_listsZ   s    &$r*   c                   @   sd   e Zd ZdZdZdd„ Zdd„ Zdd„ Zd	d
„ ZeZ	dd„ Z
dd„ Zdd„ Zdd„ ZeZd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                 C   s€   || _ t|tƒrlt|ƒD ]L\}}t|tƒrB| j j t|ƒ¡||< qt|| j jjƒs| j j |¡||< q|| _	t
| j	ƒd | _d S )Né   )Úparentr   ÚlistÚ	enumerateÚintr	   Ú
from_sympyr   ÚdtypeÚ
listofpolyr'   Úorder)r   Zlist_of_polyr-   ÚiÚjr   r   r   r   Š   s    

zRecurrenceOperator.__init__c                    sª   | j }| jj‰ t|tƒsFt|| jjjƒs>| jj t|ƒ¡g}qL|g}n|j }dd„ }||d |ƒ}‡ fdd„}tdt	|ƒƒD ] }||ƒ}t
|||| |ƒƒ}q|t|| jƒS )zŸ
        Multiplies two Operators and returns another
        RecurrenceOperator instance using the commutation rule
        Sn * a(n) = a(n + 1) * Sn
        c                 S   s8   t |tƒr*g }|D ]}| ||  ¡ q|S | | gS d S ©N)r   r.   Úappend)r%   Úlistofotherr)   r5   r   r   r   Ú_mul_dmp_diffop¯   s    
z3RecurrenceOperator.__mul__.<locals>._mul_dmp_diffopr   c                    s„   ˆ j g}t| tƒrR| D ]8}ˆ  |¡ ˆ jd ˆ jd tj ¡}| ˆ  	|¡¡ qn.|  ˆ jd ˆ jd tj ¡}| ˆ  	|¡¡ |S )Nr   )
r   r   r.   Úto_sympyÚsubsÚgensr   ZOner8   r1   )r%   r)   r5   r6   ©r	   r   r   Ú
_mul_Sni_b»   s    
$z.RecurrenceOperator.__mul__.<locals>._mul_Sni_br,   )r3   r-   r	   r   r   r2   r1   r   Úranger'   r*   )r   r   Z
listofselfr9   r:   r)   r?   r5   r   r>   r   Ú__mul__›   s    
	zRecurrenceOperator.__mul__c                 C   sh   t |tƒsdt |tƒrt|ƒ}t || jjjƒs:| jj |¡}g }| jD ]}| 	|| ¡ qDt|| jƒS d S r7   )
r   r   r0   r   r-   r	   r2   r1   r3   r8   )r   r   r)   r6   r   r   r   Ú__rmul__Ñ   s    


zRecurrenceOperator.__rmul__c                 C   sž   t |tƒr$t| j|jƒ}t|| jƒS t |tƒr6t|ƒ}| j}t || jjjƒs^| jj 	|¡g}n|g}g }| 
|d |d  ¡ ||dd … 7 }t|| jƒS d S )Nr   r,   )r   r   r*   r3   r-   r0   r   r	   r2   r1   r8   )r   r   r)   Z	list_selfZ
list_otherr   r   r   Ú__add__à   s    

zRecurrenceOperator.__add__c                 C   s   | d|  S ©Néÿÿÿÿr   r   r   r   r   Ú__sub__÷   s    zRecurrenceOperator.__sub__c                 C   s   d|  | S rD   r   r   r   r   r   Ú__rsub__ú   s    zRecurrenceOperator.__rsub__c                 C   s”   |dkr| S t | jjjg| jƒ}|dkr,|S | j| jjjkrd| jjjg| | jjjg }t || jƒS | }|d rx||9 }|dL }|s†q�||9 }qh|S )Nr,   r   é   )r   r-   r	   r   r3   r   r   )r   ÚnÚresultr)   Úxr   r   r   Ú__pow__ý   s     
zRecurrenceOperator.__pow__c                 C   s¦   | j }d}t|ƒD ]Ž\}}|| jjjkr*q| jj |¡}|dkrV|dt|ƒ d 7 }q|rb|d7 }|dkr€|dt|ƒ d 7 }q|dt|ƒ d d t|ƒ 7 }q|S )	NÚ r   ú(ú)z + r,   z)SnzSn**)r3   r/   r-   r	   r   r;   r   )r   r3   Z	print_strr5   r6   r   r   r   r     s     "zRecurrenceOperator.__str__c                 C   sn   t |tƒr,| j|jkr&| j|jkr&dS dS n>| jd |krf| jdd … D ]}|| jjjk	rH dS qHdS dS d S )NTFr   r,   )r   r   r3   r-   r	   r   )r   r   r5   r   r   r   r   ,  s    
zRecurrenceOperator.__eq__N)r   r   r   r    Z_op_priorityr   rA   rB   rC   Ú__radd__rF   rG   rL   r   r!   r   r   r   r   r   r   b   s   %6r   c                   @   s0   e Zd ZdZg fdd„Zdd„ ZeZd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                 C   sP   || _ t|tƒs|g| _n|| _t| jƒdkr6d| _nd| _|jjjd | _	d S )Nr   FT)
Ú
recurrencer   r.   Úu0r'   Ú_have_init_condr-   r	   r=   rI   )r   rR   rS   r   r   r   r   C  s    

zHolonomicSequence.__init__c                 C   sf   d| j  ¡ t| jƒf }| js"|S d}d}| jD ]$}|dt|ƒt|ƒf 7 }|d7 }q0|| }|S d S )NzHolonomicSequence(%s, %s)rM   r   z, u(%s) = %sr,   )rR   r!   r   rI   rT   rS   )r   Zstr_solZcond_strZseq_strr5   r)   r   r   r   r!   P  s    

zHolonomicSequence.__repr__c                 C   sN   | j |j krF| j|jkr@| jr:|jr:| j|jkr4dS dS qDdS qJdS ndS d S r   )rR   rI   rT   rS   r   r   r   r   r   `  s    zHolonomicSequence.__eq__N)r   r   r   r    r   r!   r   r   r   r   r   r   rQ   <  s
   rQ   N)r    Zsympy.core.singletonr   Zsympy.core.symbolr   r   Zsympy.printingr   Zsympy.core.sympifyr   r   r   r*   r   rQ   r   r   r   r   Ú<module>   s   ; [