o
    8Va*                     @   sn   d Z ddlmZ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    )symbolsSymbolS)sstr)sympifyc                 C   s   t | |}||jfS )a9  
    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.polys.domains 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	generatorZring r   </usr/lib/python3/dist-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.polys.domains 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   sh   || _ t|j|jg| | _|d u rtddd| _d S t|tr(t|dd| _d S t|t	r2|| _d S 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   I   s   z!RecurrenceOperatorAlgebra.__str__c                 C   s    | j |j kr| j|jkrdS dS NTF)r	   r   r   otherr   r   r   __eq__R   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rdd t| |D |t | d   }|S dd t| |D | t |d   }|S )Nc                 S      g | ]\}}|| qS r   r   .0abr   r   r   
<listcomp>[       z_add_lists.<locals>.<listcomp>c                 S   r!   r   r   r"   r   r   r   r&   ]   r'   )lenzip)Zlist1Zlist2solr   r   r   
_add_listsY   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.polys.domains 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r6t|D ]&\}}t|tr!| j jt|||< qt|| j jjs2| j j|||< q|| _	t
| j	d | _d S )N   )parentr   list	enumerateintr	   
from_sympyr   dtype
listofpolyr(   Zorder)r   Zlist_of_polyr.   ijr   r   r   r      s   

zRecurrenceOperator.__init__c                    s   | j }| jj t|ts#t|| jjjs| jjt|g}n|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   s4   t |trg }|D ]	}|||   q	|S | | g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r*| D ]} | jd  jd tj }| 	| q|S |  jd  jd tj }| 	| |S )Nr   )
r   r   r/   Zto_sympyZsubsgensr   ZOner8   r2   )r%   r*   r5   r6   r	   r   r   
_mul_Sni_b   s   
$z.RecurrenceOperator.__mul__.<locals>._mul_Sni_br-   )r4   r.   r	   r   r   r3   r2   r   ranger(   r+   )r   r   Z
listofselfr9   r:   r*   r=   r5   r   r<   r   __mul__   s   
	zRecurrenceOperator.__mul__c                 C   sh   t |ts2t |trt|}t || jjjs| jj|}g }| jD ]	}|	||  q"t|| jS d S r7   )
r   r   r1   r   r.   r	   r3   r2   r4   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rt|}| j}t || jjjs/| jj	|g}n|g}g }|
|d |d   ||dd  7 }t|| jS )Nr   r-   )r   r   r+   r4   r.   r1   r   r	   r3   r2   r8   )r   r   r*   Z	list_selfZ
list_otherr   r   r   __add__   s   

zRecurrenceOperator.__add__c                 C   s   | d|  S Nr   r   r   r   r   __sub__      zRecurrenceOperator.__sub__c                 C   s   d|  | S rB   r   r   r   r   r   __rsub__   rE   zRecurrenceOperator.__rsub__c                 C   s   |dkr| S |dkrt | jjjg| jS | j| jjjkr<g }td|D ]
}|| jjj q#|| jjj t || jS |d dkrL| |d  }||  S |d dkr\| |d  }|| S d S )Nr-   r      )	r   r.   r	   r   r4   r   r>   r8   r   )r   nr*   r5   Z	powreducer   r   r   __pow__   s"   zRecurrenceOperator.__pow__c                 C   s   | j }d}t|D ]@\}}|| jjjkrq	|dkr$|dt| d 7 }q	|r*|d7 }|dkr9|dt| d 7 }q	|dt| d d t| 7 }q	|S )	N r   ()z + r-   z)SnzSn**)r4   r0   r.   r	   r   r   )r   r4   Z	print_strr5   r6   r   r   r   r     s   "zRecurrenceOperator.__str__c                 C   sh   t |tr| j|jkr| j|jkrdS dS | jd |kr2| jdd  D ]}|| jjjur/ dS q#dS dS )NTFr   r-   )r   r   r4   r.   r	   r   )r   r   r5   r   r   r   r   +  s   
zRecurrenceOperator.__eq__N)r   r   r   r   Z_op_priorityr   r?   r@   rA   __radd__rD   rF   rI   r   r    r   r   r   r   r   r   a   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rd| _nd| _|jjjd | _	d S )Nr   FT)

recurrencer   r/   u0r(   _have_init_condr.   r	   r;   rH   )r   rO   rP   r   r   r   r   B  s   

zHolonomicSequence.__init__c                 C   sb   d| j  t| jf }| js|S d}d}| jD ]}|dt|t|f 7 }|d7 }q|| }|S )NzHolonomicSequence(%s, %s)rJ   r   z, u(%s) = %sr-   )rO   r    r   rH   rQ   rP   )r   Zstr_solZcond_strZseq_strr5   r*   r   r   r   r    O  s   

zHolonomicSequence.__repr__c                 C   sD   | j |j kr | j|jkr| jr|jr| j|jkrdS dS dS dS dS r   )rO   rH   rQ   rP   r   r   r   r   r   _  s   zHolonomicSequence.__eq__N)r   r   r   r   r   r    r   r   r   r   r   r   rN   ;  s    rN   N)r   Zsympyr   r   r   Zsympy.printingr   Zsympy.core.sympifyr   r   r   r+   r   rN   r   r   r   r   <module>   s    ; [