B
    dd*                 @   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   g/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/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   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rpxXt|D ]L\}}t|trD| j jt|||< qt|| j jjs| j j|||< qW || _	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}x2tdt	|D ] }||}t
|||| |}q~W 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   s<   t |tr.g }x|D ]}|||   qW |S | | gS d S )N)r   r+   append)r"   listofotherr&   r2   r   r   r   _mul_dmp_diffop   s    

z3RecurrenceOperator.__mul__.<locals>._mul_dmp_diffopr   c                s    j g}t| trVxp| D ]8} | jd  jd tj }| 	| qW n.|  jd  jd tj }| 	| |S )Nr   )
r   r   r+   Zto_sympysubsgensr   ZOner4   r.   )r"   r&   r2   r3   )r	   r   r   
_mul_Sni_b   s    

$z.RecurrenceOperator.__mul__.<locals>._mul_Sni_br)   )r0   r*   r	   r   r   r/   r.   r   ranger$   r'   )r   r   Z
listofselfr5   r6   r&   r9   r2   r   )r	   r   __mul__   s    
	zRecurrenceOperator.__mul__c             C   sl   t |tsht |trt|}t || jjjs:| jj|}g }x| jD ]}|	||  qFW t|| jS d S )N)
r   r   r-   r   r*   r	   r/   r.   r0   r4   )r   r   r&   r3   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'   r0   r*   r-   r   r	   r/   r.   r4   )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   r   __sub__   s    zRecurrenceOperator.__sub__c             C   s   d|  | S )Nr>   r   )r   r   r   r   r   __rsub__   s    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 }x"td|D ]}|| jjj qHW || jjj t || jS |d dkr| |d  }||  S |d dkr| |d  }|| S d S )Nr)   r      )	r   r*   r	   r   r0   r   r:   r4   r   )r   nr&   r2   Z	powreducer   r   r   __pow__   s     zRecurrenceOperator.__pow__c             C   s   | j }d}xt|D ]\}}|| jjjkr,q|dkrJ|dt| d 7 }q|rV|d7 }|dkrt|dt| d 7 }q|dt| d d t| 7 }qW |S )	N r   ()z + r)   z)SnzSn**)r0   r,   r*   r	   r   r   )r   r0   Z	print_strr2   r3   r   r   r   r     s    $zRecurrenceOperator.__str__c             C   sp   t |tr,| j|jkr&| j|jkr&dS dS n@| jd |krhx(| jdd  D ]}|| jjjk	rJdS qJW dS dS d S )NTFr   r)   )r   r   r0   r*   r	   r   )r   r   r2   r   r   r   r   ,  s    
zRecurrenceOperator.__eq__N)r   r   r   r   Z_op_priorityr   r;   r<   r=   __radd__r?   r@   rC   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	   r8   rB   )r   rI   rJ   r   r   r   r   C  s    

zHolonomicSequence.__init__c             C   sj   d| j  t| jf }| js"|S d}d}x.| jD ]$}|dt|t|f 7 }|d7 }q2W || }|S d S )NzHolonomicSequence(%s, %s)rD   r   z, u(%s) = %sr)   )rI   r   r   rB   rK   rJ   )r   Zstr_solZcond_strZseq_strr2   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 )NTF)rI   rB   rK   rJ   )r   r   r   r   r   r   `  s    zHolonomicSequence.__eq__N)r   r   r   r   r   r   r   r   r   r   r   r   rH   <  s
   rH   N)r   Zsympy.core.singletonr   Zsympy.core.symbolr   r   Zsympy.printingr   Zsympy.core.sympifyr   r   r   r'   r   rH   r   r   r   r   <module>   s   ; [