o
    ohai                    @   s  d Z ddlmZmZmZ ddlmZmZmZm	Z	m
Z
mZmZmZ ddlmZ ddlmZ ddlmZmZ ddlmZ ddlmZmZmZ dd	lmZmZmZ dd
lm Z m!Z! ddl"m#Z# ddl$m%Z%m&Z&m'Z' ddl(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z. ddl/m0Z0 ddl1m2Z2m3Z3 ddl4m5Z5 ddl6m7Z7 ddl8m9Z9 ddl:m;Z; ddl<m=Z=m>Z> ddl?m@Z@ ddlAmBZB ddlCmDZD ddlEmFZF ddlGmHZH ddlImJZJ ddlKmLZL ddlMmNZN ddlOmPZP ddlQmRZR dd lSmTZTmUZUmVZV dd!lWmXZXmYZYmZZZm[Z[ d"d# Z\d$d% Z]G d&d' d'Z^G d(d) d)Z_G d*d+ d+Z`dMd-d.Zadd,d/e=fd0d1Zbed2Zcd3add3aedd4lfmgZg dNd5d6ZhdOd7d8Zid9d: Zjd;d< Zkd=d> Zld?d@ ZmdAdB ZndPdCdDZodd3d3e=d/fdEdFZpd/e=fdGdHZqe=fdIdJZrdKdL Zsd3S )QzL
This module implements Holonomic Functions and
various operations on them.
    )AddMulPow)NaNInfinityNegativeInfinityFloatIpiequal_valued
int_valued)S)ordered)DummySymbol)sympify)binomial	factorialrf)	exp_polarexplog)coshsinh)sqrt)cossinsinc)CiShiSierferfcerfi)gamma)hypermeijerg)	meijerint)Matrix)PolyElement)FracElement)QQRR)DMF)roots)Poly)DomainMatrix)sstr)limit)Order)hyperexpand)	nsimplify)solve   )HolonomicSequenceRecurrenceOperatorRecurrenceOperators)NotPowerSeriesErrorNotHyperSeriesErrorSingularityErrorNotHolonomicErrorc                    sD    fdd}  |\}}|jd }|d|f| }||  }|S )Nc                    s   t |  jS N)r0   onesdomain)shaper m/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/sympy/holonomic/holonomic.py<lambda>+   s    z(_find_nonzero_solution.<locals>.<lambda>r   r7   )_solverB   	transpose)rD   homosysr@   
particular	nullspacenullitynullpartsolrE   rC   rF   _find_nonzero_solution*   s   
rP   c                 C   s   t | |}||jfS )a  
    This function is used to create annihilators using ``Dx``.

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

    Returns an Algebra of Differential Operators also called Weyl Algebra
    and the operator for differentiation i.e. the ``Dx`` operator.

    Parameters
    ==========

    base:
        Base polynomial ring for the algebra.
        The base polynomial ring is the ring of polynomials in :math:`x` that
        will appear as coefficients in the operators.
    generator:
        Generator of the algebra which can
        be either a noncommutative ``Symbol`` or a string. e.g. "Dx" or "D".

    Examples
    ========

    >>> from sympy import ZZ
    >>> from sympy.abc import x
    >>> from sympy.holonomic.holonomic import DifferentialOperators
    >>> R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
    >>> R
    Univariate Differential Operator Algebra in intermediate Dx over the base ring ZZ[x]
    >>> Dx*x
    (1) + (x)*Dx
    )DifferentialOperatorAlgebraderivative_operator)base	generatorringrE   rE   rF   DifferentialOperators4   s   
"
rV   c                   @   s,   e Zd ZdZdd Zdd ZeZdd ZdS )	rQ   a  
    An Ore Algebra is a set of noncommutative polynomials in the
    intermediate ``Dx`` and coefficients in a base polynomial ring :math:`A`.
    It follows the commutation rule:

    .. math ::
       Dxa = \sigma(a)Dx + \delta(a)

    for :math:`a \subset A`.

    Where :math:`\sigma: A \Rightarrow A` is an endomorphism and :math:`\delta: A \rightarrow A`
    is a skew-derivation i.e. :math:`\delta(ab) = \delta(a) b + \sigma(a) \delta(b)`.

    If one takes the sigma as identity map and delta as the standard derivation
    then it becomes the algebra of Differential Operators also called
    a Weyl Algebra i.e. an algebra whose elements are Differential Operators.

    This class represents a Weyl Algebra and serves as the parent ring for
    Differential Operators.

    Examples
    ========

    >>> from sympy import ZZ
    >>> from sympy import symbols
    >>> from sympy.holonomic.holonomic import DifferentialOperators
    >>> x = symbols('x')
    >>> R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
    >>> R
    Univariate Differential Operator Algebra in intermediate Dx over the base ring
    ZZ[x]

    See Also
    ========

    DifferentialOperator
    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 )NDxF)commutative)	rS   DifferentialOperatorzeroonerR   r   
gen_symbol
isinstancestr)selfrS   rT   rE   rE   rF   __init__   s   


z$DifferentialOperatorAlgebra.__init__c                 C   s    dt | j d | j  }|S )Nz9Univariate Differential Operator Algebra in intermediate z over the base ring )r1   r\   rS   __str__)r_   stringrE   rE   rF   ra      s   z#DifferentialOperatorAlgebra.__str__c                 C   s   | j |j ko| j|jkS r?   )rS   r\   r_   otherrE   rE   rF   __eq__   s   
z"DifferentialOperatorAlgebra.__eq__N)__name__
__module____qualname____doc__r`   ra   __repr__re   rE   rE   rE   rF   rQ   Z   s    &rQ   c                   @   s|   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dd Zdd ZeZdd Zdd ZdS )rY   a  
    Differential Operators are elements of Weyl Algebra. The Operators
    are defined by a list of polynomials in the base ring and the
    parent ring of the Operator i.e. the algebra it belongs to.

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

    Takes a list of polynomials for each power of ``Dx`` and the
    parent ring which must be an instance of DifferentialOperatorAlgebra.

    A Differential Operator can be created easily using
    the operator ``Dx``. See examples below.

    Examples
    ========

    >>> from sympy.holonomic.holonomic import DifferentialOperator, DifferentialOperators
    >>> from sympy import ZZ
    >>> from sympy import symbols
    >>> x = symbols('x')
    >>> R, Dx = DifferentialOperators(ZZ.old_poly_ring(x),'Dx')

    >>> DifferentialOperator([0, 1, x**2], R)
    (1)*Dx + (x**2)*Dx**2

    >>> (x*Dx*x + 1 - Dx**2)**2
    (2*x**2 + 2*x + 1) + (4*x**3 + 2*x**2 - 4)*Dx + (x**4 - 6*x - 2)*Dx**2 + (-2*x**2)*Dx**3 + (1)*Dx**4

    See Also
    ========

    DifferentialOperatorAlgebra
       c                 C   s   || _ | j j}t|jd tr|jd n|jd d | _t|D ]\}}t||js4|t	|||< q ||
|||< q || _t| jd | _dS )z
        Parameters
        ==========

        list_of_poly:
            List of polynomials belonging to the base ring of the algebra.
        parent:
            Parent algebra of the operator.
        r   r7   N)parentrS   r]   gensr   x	enumeratedtype
from_sympyr   to_sympy
listofpolylenorder)r_   list_of_polyrl   rS   ijrE   rE   rF   r`      s   *zDifferentialOperator.__init__c                    s    j }t|tr|j }nt| jjjr|g}n
 jjt|g}dd }||d |} fdd}tdt	|D ]}||}t
|||| |}q:t| jS )z
        Multiplies two DifferentialOperator and returns another
        DifferentialOperator instance using the commutation rule
        Dx*a = a*Dx + a'
        c                    s&   t |tr fdd|D S  | gS )Nc                    s   g | ]}|  qS rE   rE   .0rw   brE   rF   
<listcomp>       zIDifferentialOperator.__mul__.<locals>._mul_dmp_diffop.<locals>.<listcomp>)r]   list)r|   listofotherrE   r{   rF   _mul_dmp_diffop   s   

z5DifferentialOperator.__mul__.<locals>._mul_dmp_diffopr   c                    st    j jjg}g }t| tr| D ]}|| ||  qn| j j|  | j j|   t||S r?   )	rl   rS   rZ   r]   r   appenddiffrq   
_add_lists)r|   sol1sol2rw   r_   rE   rF   
_mul_Dxi_b   s   


z0DifferentialOperator.__mul__.<locals>._mul_Dxi_br7   )rs   r]   rY   rl   rS   rp   rq   r   rangert   r   )r_   rd   
listofselfr   r   rO   r   rw   rE   r   rF   __mul__   s   
zDifferentialOperator.__mul__c                    sP   t  ts&t  | jjjs| jjt   fdd| jD }t|| jS d S )Nc                    s   g | ]} | qS rE   rE   rz   rx   rd   rE   rF   r}     r~   z1DifferentialOperator.__rmul__.<locals>.<listcomp>)r]   rY   rl   rS   rp   rq   r   rs   )r_   rd   rO   rE   r   rF   __rmul__  s   
zDifferentialOperator.__rmul__c                 C   s   t |trt| j|j}t|| jS | j}t || jjjs(| jjt|g}n|g}|d |d  g|dd   }t|| jS )Nr   r7   )	r]   rY   r   rs   rl   rS   rp   rq   r   )r_   rd   rO   	list_self
list_otherrE   rE   rF   __add__  s   
zDifferentialOperator.__add__c                 C   s   | d|  S NrE   rc   rE   rE   rF   __sub__)     zDifferentialOperator.__sub__c                 C   s   d|  | S r   rE   rc   rE   rE   rF   __rsub__,  r   zDifferentialOperator.__rsub__c                 C      d|  S r   rE   r   rE   rE   rF   __neg__/     zDifferentialOperator.__neg__c                 C      | t j|  S r?   r   Onerc   rE   rE   rF   __truediv__2     z DifferentialOperator.__truediv__c                 C   s   |dkr| S t | jjjg| j}|dkr|S | j| jjjkr2| jjjg| | jjjg }t || jS | }	 |d r=||9 }|dL }|sF	 |S ||9 }q5)Nr7   r   T   )rY   rl   rS   r[   rs   rR   rZ   )r_   nresultrO   rn   rE   rE   rF   __pow__5  s$   zDifferentialOperator.__pow__c                 C   s   | j }d}t|D ]O\}}|| jjjkrq	| jj|}|dkr+|dt| d 7 }q	|r1|d7 }|dkrD|dt| d| jj  7 }q	|dt| d d| jj  t| 7 }q	|S )	N r   ()z + r7   z)*%sz*%s**)rs   ro   rl   rS   rZ   rr   r1   r\   )r_   rs   	print_strrw   rx   rE   rE   rF   ra   I  s    *zDifferentialOperator.__str__c                    sP   t |tr j|jko j|jkS  jd |ko't fdd jdd  D S )Nr   c                 3   s    | ]
}| j jju V  qd S r?   rl   rS   rZ   ry   r   rE   rF   	<genexpr>i      z.DifferentialOperator.__eq__.<locals>.<genexpr>r7   )r]   rY   rs   rl   allrc   rE   r   rF   re   d  s   

zDifferentialOperator.__eq__c                 C   s$   | j j}|t|| jd | jv S )zH
        Checks if the differential equation is singular at x0.
        r   )rl   rS   r.   rr   rs   rn   )r_   x0rS   rE   rE   rF   is_singulark  s   z DifferentialOperator.is_singularN)rf   rg   rh   ri   _op_priorityr`   r   r   r   __radd__r   r   r   r   r   ra   rj   re   r   rE   rE   rE   rF   rY      s"    #.	rY   c                   @   s  e Zd ZdZdZdDddZdd ZeZd	d
 Zdd Z	dd Z
dd Zdd ZdEd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d$d% Zd&d' Zd(d) ZdFd+d,ZdFd-d.ZdGd0d1Zd2d3 ZdHd6d7Zd8d9 Zd:d; ZdId<d=Z d>d? Z!dJd@dAZ"dBdC Z#dS )KHolonomicFunctiona
  
    A Holonomic Function is a solution to a linear homogeneous ordinary
    differential equation with polynomial coefficients. This differential
    equation can also be represented by an annihilator i.e. a Differential
    Operator ``L`` such that :math:`L.f = 0`. For uniqueness of these functions,
    initial conditions can also be provided along with the annihilator.

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

    Holonomic functions have closure properties and thus forms a ring.
    Given two Holonomic Functions f and g, their sum, product,
    integral and derivative is also a Holonomic Function.

    For ordinary points initial condition should be a vector of values of
    the derivatives i.e. :math:`[y(x_0), y'(x_0), y''(x_0) ... ]`.

    For regular singular points initial conditions can also be provided in this
    format:
    :math:`{s0: [C_0, C_1, ...], s1: [C^1_0, C^1_1, ...], ...}`
    where s0, s1, ... are the roots of indicial equation and vectors
    :math:`[C_0, C_1, ...], [C^0_0, C^0_1, ...], ...` are the corresponding initial
    terms of the associated power series. See Examples below.

    Examples
    ========

    >>> from sympy.holonomic.holonomic import HolonomicFunction, DifferentialOperators
    >>> from sympy import QQ
    >>> from sympy import symbols, S
    >>> x = symbols('x')
    >>> R, Dx = DifferentialOperators(QQ.old_poly_ring(x),'Dx')

    >>> p = HolonomicFunction(Dx - 1, x, 0, [1])  # e^x
    >>> q = HolonomicFunction(Dx**2 + 1, x, 0, [0, 1])  # sin(x)

    >>> p + q  # annihilator of e^x + sin(x)
    HolonomicFunction((-1) + (1)*Dx + (-1)*Dx**2 + (1)*Dx**3, x, 0, [1, 2, 1])

    >>> p * q  # annihilator of e^x * sin(x)
    HolonomicFunction((2) + (-2)*Dx + (1)*Dx**2, x, 0, [0, 1])

    An example of initial conditions for regular singular points,
    the indicial equation has only one root `1/2`.

    >>> HolonomicFunction(-S(1)/2 + x*Dx, x, 0, {S(1)/2: [1]})
    HolonomicFunction((-1/2) + (x)*Dx, x, 0, {1/2: [1]})

    >>> HolonomicFunction(-S(1)/2 + x*Dx, x, 0, {S(1)/2: [1]}).to_expr()
    sqrt(x)

    To plot a Holonomic Function, one can use `.evalf()` for numerical
    computation. Here's an example on `sin(x)**2/x` using numpy and matplotlib.

    >>> import sympy.holonomic # doctest: +SKIP
    >>> from sympy import var, sin # doctest: +SKIP
    >>> import matplotlib.pyplot as plt # doctest: +SKIP
    >>> import numpy as np # doctest: +SKIP
    >>> var("x") # doctest: +SKIP
    >>> r = np.linspace(1, 5, 100) # doctest: +SKIP
    >>> y = sympy.holonomic.expr_to_holonomic(sin(x)**2/x, x0=1).evalf(r) # doctest: +SKIP
    >>> plt.plot(r, y, label="holonomic function") # doctest: +SKIP
    >>> plt.show() # doctest: +SKIP

    rk   r   Nc                 C   s   || _ || _|| _|| _dS )ap  

        Parameters
        ==========

        annihilator:
            Annihilator of the Holonomic Function, represented by a
            `DifferentialOperator` object.
        x:
            Variable of the function.
        x0:
            The point at which initial conditions are stored.
            Generally an integer.
        y0:
            The initial condition. The proper format for the initial condition
            is described in class docstring. To make the function unique,
            length of the vector `y0` should be equal to or greater than the
            order of differential equation.
        N)y0r   annihilatorrn   )r_   r   rn   r   r   rE   rE   rF   r`     s   
zHolonomicFunction.__init__c                 C   sP   |   rdt| jt| jt| jt| jf }|S dt| jt| jf }|S )Nz!HolonomicFunction(%s, %s, %s, %s)zHolonomicFunction(%s, %s))_have_init_condr^   r   r1   rn   r   r   )r_   str_solrE   rE   rF   ra     s   

zHolonomicFunction.__str__c           	         s   | j jj |j jj j}j} kr| |fS ||| j}t|t| j jj	\}} fdd| j j
D }fdd|j j
D }t||}t||}t|| j| j| j}t||j|j|j}||fS )z^
        Unifies the base polynomial ring of a given two Holonomic
        Functions.
        c                       g | ]}  |qS rE   rr   ry   )R1rE   rF   r}         z+HolonomicFunction.unify.<locals>.<listcomp>c                    r   rE   r   ry   )R2rE   rF   r}     r   )r   rl   rS   domunifyold_poly_ringrn   rV   r^   r\   rs   rY   r   r   r   )	r_   rd   dom1dom2R	newparent_r   r   rE   )r   r   rF   r     s   



zHolonomicFunction.unifyc                 C   s$   t | jtrdS t | jtrdS dS )z
        Returns True if the function have singular initial condition
        in the dictionary format.

        Returns False if the function have ordinary initial condition
        in the list format.

        Returns None for all other cases.
        TFN)r]   r   dictr   r   rE   rE   rF   is_singularics   s
   z HolonomicFunction.is_singularicsc                 C   s
   t | jS )z@
        Checks if the function have initial condition.
        )boolr   r   rE   rE   rF   r     s   
z!HolonomicFunction._have_init_condc                    s   t | jd  | j  }t| jdkr> t kr@ dkrBt  tjg  }| fddt|D 7 }t| j| j	| j
|S dS dS dS )zP
        Converts a singular initial condition to ordinary if possible.
        r   r7   c                    s    g | ]\}}|t  |  qS rE   r   rz   rw   rx   arE   rF   r}           z9HolonomicFunction._singularics_to_ord.<locals>.<listcomp>N)r   r   rt   intr   Zeroro   r   r   rn   r   )r_   r|   r   rE   r   rF   _singularics_to_ord  s   
"z%HolonomicFunction._singularics_to_ordc                 C   s  | j jj|j jjkr| |\}}|| S | j j}|j j}t||}| j jj}| }| j g}	|j g}
| j jj}t|| D ]}||	d  }|		| q>t|| D ]}||
d  }|
	| qR|	|
 }g }|D ]-}g }t|d D ]}|t
|jkr|	|j qr|	||j|   qr|	| qht|t
||d f| }t|d df|}t||}|jr'|d7 }||	d  }|		| ||
d  }|
	| |	|
 }g }|D ]-}g }t|d D ]}|t
|jkr|	|j q|	||j|   q|	| qt|t
||d f| }t|d df|}t||}|js| d |d |  }t|| j j}|| j  }t|j| j jdd}|  rS| sYt|| jS |  dkr| dkr| j|jkrt| |j}t||j}dd t||D }t|| j| j|S | j d}|j d}| jdkr|s|s| |d S |jdkr|s|s| d| S | j | j}|j | j}|s|s| || j S | |j| S | j|jkrt|| jS d }d }|  dkr| dkrd	d t| j D }t!j"|i}|j }n5|  dkr6| dkr6d
d t|j D }| j }t!j"|i}n|  dkrJ| dkrJ| j }|j }i }|D ] }||v rgdd t|| || D ||< qN|| ||< qN|D ]}||vr~|| ||< qqt|| j| j|S )Nr   r7   Fnegativec                 S      g | ]\}}|| qS rE   rE   rz   r   r|   rE   rE   rF   r}         z-HolonomicFunction.__add__.<locals>.<listcomp>r   Tc                 S      g | ]
\}}|t | qS rE   r   r   rE   rE   rF   r}         c                 S   r   rE   r   r   rE   rE   rF   r}     r   c                 S   r   rE   rE   r   rE   rE   rF   r}     r   )#r   rl   rS   r   ru   max	get_fieldrR   r   r   rt   rs   rZ   newto_listr0   rI   zerosrP   is_zero_matrixflat
_normalizer   r   rn   r   r   
_extend_y0zipr   
change_icsro   r   r   r   )r_   rd   r   r|   deg1deg2dimr   Krowsself	rowsothergenrw   diff1diff2rowrD   exprprJ   rO   r   y1y2r   selfat0otherat0selfatx0	otheratx0_y0rE   rE   rF   r   $  s   









$
zHolonomicFunction.__add__Fc              	   C   s<  | j jj}|  dkro|  }|r|j||dS i }| jD ]<}| j| }g }t|D ](\}	}
|
dkr9|t	j
 q*||	 d dkrEtd||
t	||	 d   q*|||d < qt|drctdt| j | | j| j|S |  s|rt| j | | j| jt	j
gS t| j | | jS t|drt|dkr|d | jkr| j}|d }|d	 }d}nd
}t	j
g}|| j7 }t| j | | j| j|}|s|S ||kr>z| }W n ttfy   d}Y nw |r|| j|}t|tr|| j|}n||}|| jkr|d | |d< t| j | | j||S t	|jr>|r5|| j|}t|tr1|| j|}|| S ||}|| S || jkrOt| j | | j||S t	|jrz%t| j | | j|| }|| j|}t|tss|W S || j|W S  ttfy   t| j | | j||| Y S w t| j | | jS )az  
        Integrates the given holonomic function.

        Examples
        ========

        >>> from sympy.holonomic.holonomic import HolonomicFunction, DifferentialOperators
        >>> from sympy import QQ
        >>> from sympy import symbols
        >>> x = symbols('x')
        >>> R, Dx = DifferentialOperators(QQ.old_poly_ring(x),'Dx')
        >>> HolonomicFunction(Dx - 1, x, 0, [1]).integrate((x, 0, x))  # e^x - 1
        HolonomicFunction((-1)*Dx + (1)*Dx**2, x, 0, [0, 1])
        >>> HolonomicFunction(Dx**2 + 1, x, 0, [1, 0]).integrate((x, 0, x))
        HolonomicFunction((1)*Dx + (1)*Dx**3, x, 0, [0, 1, 0])
        T)initcondr   r7   z1logarithmic terms in the series are not supported__iter__z4Definite integration for singular initial conditions   r   FN)r   rl   rR   r   r   	integrater   ro   r   r   r   NotImplementedErrorhasattrr   rn   r   r   rt   to_exprr<   r;   subsr]   r   r2   evalf	is_Number)r_   limitsr   DrD   r   rw   cc2rx   cjr   r   r|   definiteindefinite_integralindefinite_exprloweruppers
indefiniterE   rE   rF   r     s   









 zHolonomicFunction.integratec           	         s  | dd |r,|d | jkrtjS t|dkr,| }t|d D ]	}||d }q |S | j}|jd |j	j
jkrA|jdkrAtjS |jd |j	j
jkrzt|jdd |j	}|  rt|  dkrnt|| j| j| jdd S t|| jS t|| jS |j	j
}|   fdd	|jD fd
d	dd D }|d j t| }t| j jg}t|dd | jj	dd}|  r|  dkrt|| jS t| |jd dd }t|| j| j|S )aK  
        Differentiation of the given Holonomic function.

        Examples
        ========

        >>> from sympy.holonomic.holonomic import HolonomicFunction, DifferentialOperators
        >>> from sympy import ZZ
        >>> from sympy import symbols
        >>> x = symbols('x')
        >>> R, Dx = DifferentialOperators(ZZ.old_poly_ring(x),'Dx')
        >>> HolonomicFunction(Dx**2 + 1, x, 0, [0, 1]).diff().to_expr()
        cos(x)
        >>> HolonomicFunction(Dx - 2, x, 0, [1]).diff().to_expr()
        2*exp(2*x)

        See Also
        ========

        integrate
        evaluateTr   r   r7   NFc                       g | ]	}  | qS rE   r   r   ry   r   rE   rF   r}   m      z*HolonomicFunction.diff.<locals>.<listcomp>c                    s   g | ]}| d   qS r   rE   ry   )seq_dmfrE   rF   r}   p  r   r   )
setdefaultrn   r   r   rt   r   r   r   rs   rl   rS   rZ   ru   rY   r   r   r   r   r   r   insert_derivate_diff_eqr   r[   r   r   )	r_   argskwargsrO   rw   annr   rhsr   rE   )r   r  rF   r   4  s>   
zHolonomicFunction.diffc                 C   sH   | j |j ks| j|jkrdS |  r"| r"| j|jko!| j|jkS dS )NFT)r   rn   r   r   r   rc   rE   rE   rF   re     s
   zHolonomicFunction.__eq__c                    s  	j }tts5t	jrtd	 s	S t	|j	}	fdd|D 
t|	j	j

S 	j jjj jjkrJ	\ S j }|j	|j	|jj}|   fdd|jD  fdd|jD fddtD }fddtD } fddtd	 D  jd
 d
< fddtD g}t|d	 f  }	t d	f }
t|	|
}|jrtd	 ddD ]Ttd	 ddD ]I d	     7  < d	      7  < t   jrt    < qڈ  	j < qqtd	 D ].  jr7q+tD ]   |    7  < q; j < q+tD ]/  d
krkq^tD ]   |    7  < qo j < q^|fddtD  t|t| f  }	t|	|
}|jst| 	j jdd}	 rȈ st|	jS 	  dkrÈ  dkrÈ	j
j
krmt	|j	}t|j	}|d
 |d
  g}td	t!t|t|D ]_fddtd	 D }td	 D ]td	 D ]}| kr3t"| |< q!qd
}td	 D ]td	 D ]}|| | |  ||  7 }qGq?|| qt|	j	j
|S 	j #d
}j #d
}	j
d
kr|s|s	$d
 S j
d
kr|s|s	$d
 S 	j #	j
}j #	j
}|s|s	$	j
 S 	$j
 S 	j
j
krt|	jS d 
d 	  dkr  dkrdd t%	j&D }t'j(|i
j&n5	  dkr  dkrdd t%j&D }	j&
t'j(|in	  dkr*  dkr*	j&
j&i }
D ]ED ]?t!t
 t }
fddt|D } |vr^|| < q2dd t)||  D | < q2q.t|	j	j
|S )Nz> Can't multiply a HolonomicFunction and expressions/functions.c                    s    g | ]}t |j  jqS rE   )r/   r   rn   repr   )rd   r_   rE   rF   r}     r   z-HolonomicFunction.__mul__.<locals>.<listcomp>c                    r  rE   r	  r   r
  rE   rF   r}     r  c                    r  rE   r	  r   r
  rE   rF   r}     r  c                       g | ]}|     qS rE   rE   ry   )r   r   rE   rF   r}         c                    r  rE   rE   ry   )r|   r   rE   rF   r}     r  c                    s&   g | ]} fd dt d D qS )c                    s   g | ]} j qS rE   )rZ   ry   r
  rE   rF   r}         8HolonomicFunction.__mul__.<locals>.<listcomp>.<listcomp>r7   r   r   )r   r|   rE   rF   r}        & r7   r   c                    &   g | ]}t  D ]}| | qqS rE   r  r   r|   	coeff_mulrE   rF   r}     r  r   c                    r  rE   r  r   r  rE   rF   r}     r  Fr   c                    s"   g | ]}d d t  d D qS )c                 S   s   g | ]}d qS r  rE   ry   rE   rE   rF   r}     s    r  r7   r  r   )rw   rE   rF   r}     s   " Tc                 S   r   rE   r   r   rE   rE   rF   r}     r   c                 S   r   rE   r   r   rE   rE   rF   r}     r   c                    s8   g | ] t  fd dt d D tjdqS )c                 3   s,    | ]} |   |   V  qd S r?   rE   )rz   r|   )r   rw   rx   r   r   rE   rF   r   !  s   * z7HolonomicFunction.__mul__.<locals>.<listcomp>.<genexpr>r7   start)sumr   r   r   )rz   )rw   rx   r   r   r   rF   r}   !  s
    "
c                 S   r   rE   rE   r   rE   rE   rF   r}   &  r   )*r   r]   r   r   hasrn   r   r   r   ru   r   rl   rS   r   r   rs   r   r[   r0   rI   r   rP   r   rp   DMFdiffr   is_zerorZ   r   rt   r   r   r   minr   r   r   ro   r   r   r   r   )r_   rd   ann_selfr   	ann_otherr   self_red	other_redlin_sys_elementslin_syshomo_sysrO   sol_anny0_selfy0_othercoeffkr   r   r   r   r   r   rE   )r   r   r|   r  rw   rx   r   r   rd   r_   r   r   rF   r     s   

  	((
!$
(zHolonomicFunction.__mul__c                 C   s   | |d  S r   rE   rc   rE   rE   rF   r   +  r   zHolonomicFunction.__sub__c                 C   s   | d | S r   rE   rc   rE   rE   rF   r   .  r   zHolonomicFunction.__rsub__c                 C   r   r   rE   r   rE   rE   rF   r   1  r   zHolonomicFunction.__neg__c                 C   r   r?   r   rc   rE   rE   rF   r   4  r   zHolonomicFunction.__truediv__c                    s  | j jdkrK| j }|j | jd u rd }n
t| jd | g}|jd }|jd }t|| j| j	} fdd||fD }t
| }t|| j| j|S |dk rStd| j jj}t|| jtjtjg}	|dkri|	S | }
	 |d rt|	|
9 }	|dL }|s}	 |	S |
|
9 }
ql)Nr7   r   c                    s   g | ]} j |qS rE   )rS   rr   ry   rl   rE   rF   r}   F  r   z-HolonomicFunction.__pow__.<locals>.<listcomp>z&Negative Power on a Holonomic FunctionTr   )r   ru   rl   r   r   rs   r/   r   rn   r  rY   r   r   r>   rR   r   r   r   )r_   r   r  r   p0p1rO   ddrW   r   rn   rE   r2  rF   r   7  s8   




zHolonomicFunction.__pow__c                 C   s   t dd | jjD S )zF
        Returns the highest power of `x` in the annihilator.
        c                 s       | ]}|  V  qd S r?   degreery   rE   rE   rF   r   ]      z+HolonomicFunction.degree.<locals>.<genexpr>)r   r   rs   r   rE   rE   rF   r8  Y  s   zHolonomicFunction.degreec                    s  j j}j j} j}j jtD ]\}}t|j jjj	r-j jj
||< q| j i fddt|D }	dd t|D }
tj|
d< |
g}tdd t|D g }	 fdd|
D }t|d D ]}||d   |
| | 7  < qut|D ]}||  |
d	 |	|  | 7  < q|}
||
 t| |\}}|jdurnqft|d }||d}t|dd
 |dd}|rt|j|d |d S t|jS )a`  
        Returns function after composition of a holonomic
        function with an algebraic function. The method cannot compute
        initial conditions for the result by itself, so they can be also be
        provided.

        Examples
        ========

        >>> from sympy.holonomic.holonomic import HolonomicFunction, DifferentialOperators
        >>> from sympy import QQ
        >>> from sympy import symbols
        >>> x = symbols('x')
        >>> R, Dx = DifferentialOperators(QQ.old_poly_ring(x),'Dx')
        >>> HolonomicFunction(Dx - 1, x).composition(x**2, 0, [1])  # e^(x**2)
        HolonomicFunction((-2*x) + (1)*Dx, x, 0, [1])
        >>> HolonomicFunction(Dx**2 + 1, x).composition(x**2 - 1, 1, [1, 0])
        HolonomicFunction((4*x**3) + (-1)*Dx + (x)*Dx**2, x, 1, [1, 0])

        See Also
        ========

        from_hyper
        c                    s&   g | ]}|  j i  qS rE   )r   rn   ry   r   rs   rD   r_   rE   rF   r}     r  z1HolonomicFunction.composition.<locals>.<listcomp>c                 S      g | ]}t jqS rE   r   r   ry   rE   rE   rF   r}     r  r   c                 S   r;  rE   r<  ry   rE   rE   rF   r}     r  Tc                    s   g | ]}|  jqS rE   )r   rn   )rz   r   r   rE   rF   r}     r   r7   r   NFr   )r   rl   ru   r   rn   rs   ro   r]   rS   rp   rr   r   r   r   r   r(   rI   r   gauss_jordan_solver   r   r   r   )r_   r   r  r  r   r   r   rw   rx   r   coeffssystemhomogeneouscoeffs_nextrO   taustaurE   r:  rF   composition_  sD   
"


zHolonomicFunction.compositionTc              	      sr  | j dkr| | j  S | j| j r| j|dS i }tddd| jjjj	}t
|d\}}t| jjD ]W\}   }t|d }t|d D ]B}	|||	  }
|
dkrYqL||	 |	f|v rz|||	 |	f  ||
t|	 d | 7  < qL||
t|	 d | |||	 |	f< qLq8g }dd	 |D }t|t|}|  }| }i }g }g }t|d D ]$  |v rt fd
d| D tjd}|| q|tj qt||}|j}t|j|jd dd}| }|rt|d }t||}||7 }t| |}dd	 t|D }t||k r(t|D ]{}tj}|D ]m | d  dk r<tj|| d  < n>| d  t|k rV|| d   || d  < n$| d  |vrztd| d   || d  < ||| d     d |kr||   ||| d    7 }q'|| q t!|g|R  }t"|t#rtt||D ])}||vrtd| ||< || |v r||||   q|||  q|rt$|||fgS t$||gS tt||D ]4}||vrtd| ||< d}|D ] ||  v r| ||   d}q|s&|||  q|r3t$|||fgS t$||gS )aG  
        Finds recurrence relation for the coefficients in the series expansion
        of the function about :math:`x_0`, where :math:`x_0` is the point at
        which the initial condition is stored.

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

        If the point :math:`x_0` is ordinary, solution of the form :math:`[(R, n_0)]`
        is returned. Where :math:`R` is the recurrence relation and :math:`n_0` is the
        smallest ``n`` for which the recurrence holds true.

        If the point :math:`x_0` is regular singular, a list of solutions in
        the format :math:`(R, p, n_0)` is returned, i.e. `[(R, p, n_0), ... ]`.
        Each tuple in this vector represents a recurrence relation :math:`R`
        associated with a root of the indicial equation ``p``. Conditions of
        a different format can also be provided in this case, see the
        docstring of HolonomicFunction class.

        If it's not possible to numerically compute a initial condition,
        it is returned as a symbol :math:`C_j`, denoting the coefficient of
        :math:`(x - x_0)^j` in the power series about :math:`x_0`.

        Examples
        ========

        >>> from sympy.holonomic.holonomic import HolonomicFunction, DifferentialOperators
        >>> from sympy import QQ
        >>> from sympy import symbols, S
        >>> x = symbols('x')
        >>> R, Dx = DifferentialOperators(QQ.old_poly_ring(x),'Dx')
        >>> HolonomicFunction(Dx - 1, x, 0, [1]).to_sequence()
        [(HolonomicSequence((-1) + (n + 1)Sn, n), u(0) = 1, 0)]
        >>> HolonomicFunction((1 + x)*Dx**2 + Dx, x, 0, [0, 1]).to_sequence()
        [(HolonomicSequence((n**2) + (n**2 + n)Sn, n), u(0) = 0, u(1) = 1, u(2) = -1/2, 2)]
        >>> HolonomicFunction(-S(1)/2 + x*Dx, x, 0, {S(1)/2: [1]}).to_sequence()
        [(HolonomicSequence((n), n), u(0) = 1, 1/2, 1)]

        See Also
        ========

        HolonomicFunction.series

        References
        ==========

        .. [1] https://hal.inria.fr/inria-00070025/document
        .. [2] https://www3.risc.jku.at/publications/download/risc_2244/DIPLFORM.pdf

        r   )lbr   TintegerSnr7   c                 S      g | ]}|d  qS r  rE   ry   rE   rE   rF   r}     r~   z1HolonomicFunction.to_sequence.<locals>.<listcomp>c                 3   0    | ]\}}|d   kr|  V  qdS r   Nr   rz   r1  vrx   r  r   rE   rF   r         z0HolonomicFunction.to_sequence.<locals>.<genexpr>r  r   Zfilterc                 S   r   rE   r   r   rE   rE   rF   r}     r   C_%sF)%r   shift_xto_sequencer   r   
_frobeniusr   rl   rS   r   r:   r   ro   rs   
all_coeffsrt   r   rr   r   r%  r   r8  r!  itemsr   r   r   r9   ru   r.   keysr   r   r6   r]   r   r8   )r_   rE  dict1r   r   r   rw   	listofdmpr8  r1  r0  rO   keylistr  
smallest_ndummyseqsunknownstempru   	all_rootsmax_rootr   u0eqsoleqsr  rE   rO  rF   rV    s   
42*


 $

zHolonomicFunction.to_sequencec           *   
      sd  |   }g }g }t| D ]#}|jr||g||   q| \}}||||fg||   q|jdd d |jdd d |  g }|D ])}t|dkrY||g qJ|D ] t	 d | rl |  nq[||g qJt
dd |D }	t
dd |D }
t
d	d |D }|  d
krg }t| j D ]}t| D ] t |r|| qqnG|
r|rt|g}n=|	rdd |D dd |D  }n,|sdd |D }n"|
s|  rt| jd jdkrt|g}ndd |D }t|g}tdd
d| jjjj}t|d\}}g }td}|D ]}i }t| jjD ]g\}   }t|d }t|d D ]Q}|||  }|dkrHq9|| || f|v rq||| || f  ||t| d | | 7  < q9||t| d | | ||| || f< q9q%g }dd |D }t|t |}t dd |D }tdd |D }| }i }g }g } t|d D ]'  |v rt! fdd|" D tj#d}!||! q|tj# qt$||}|j%}"t&|j|jd dd}#|# }#|#rt |#d }$t |$|}|"|7 }"g }%|  d
kr$| j| }%n<|  dkr`|dkr`t'||kr`t|dkr`t(| |"t'| tt'|kr`fddtt'|tD }%t|%|"k rt||D ]}tj#}&|D ]s | d  dk rtj#|| d  < nD| d  t|%k r|%| d   || d  < n*| d  |vrt)|d| d    }'t|'|| d  < | || d     d |kr|&|  *||| d    7 }&qs||& qlt+|g| R  }(t,|(t-rOtt|%|"D ]/}||vrt)|d|  }'t|'||< || |(v r*|%|(||   q|%||  q|rC|t.||%||f q|t.||%|f qtt|%|"D ]:}||vrkt)|d|  }'t|'||< d})|(D ] ||  v r|% ||   d
})qo|)s|%||  qV|r|t.||%||f n
|t.||%|f |d7 }q|S ) Nc                 S      | d S )Nr7   rE   rn   rE   rE   rF   rG   j      z.HolonomicFunction._frobenius.<locals>.<lambda>)keyc                 S   rh  Nr   rE   ri  rE   rE   rF   rG   k  rj  r   c                 s   s    | ]	}t |d kV  qdS r7   N)rt   ry   rE   rE   rF   r   ~  s    z/HolonomicFunction._frobenius.<locals>.<genexpr>c                 s   s    | ]}|d kV  qdS rK  rE   ry   rE   rE   rF   r     r9  c                 s   s    | ]}t |V  qd S r?   )r   ry   rE   rE   rF   r     r9  Tc                 S   rI  r  rE   ry   rE   rE   rF   r}     r~   z0HolonomicFunction._frobenius.<locals>.<listcomp>c                 S   rI  r  rE   r   rE   rE   rF   r}     r~   c                 S   s   g | ]
}t ||ks|qS rE   r   ry   rE   rE   rF   r}     r   Fc                 S   s   g | ]}|d kr|qS r  rE   ry   rE   rE   rF   r}     r   r   rF  rH  Cr7   c                 S   rI  r  rE   ry   rE   rE   rF   r}     r~   c                 s       | ]}|d  V  qdS rm  rE   ry   rE   rE   rF   r     r9  c                 s   rp  rm  rE   ry   rE   rE   rF   r     r9  c                 3   rJ  rK  rL  rM  rO  rE   rF   r     rP  r  r   rQ  rR  c                    s   g | ]
} | t | qS rE   r   ry   )r   rE   rF   r}     r   z_%s)/	_indicialr   rZ  is_realextendas_real_imagsortrt   r   r   r   r   r   r   r%  r   r   	is_finiter   r   rl   rS   r   r:   r   ordro   rs   rX  r   rr   r   r   r!  rY  r   r9   ru   r.   r   r   chrr   r6   r]   r   r8   )*r_   rE  indicialrootsrealscomplrw   r   r|   grpindependentallposallintrootstoconsiderposrootsr   r   r   finalsolcharr   r[  r\  r8  r1  r0  rO   r]  r  degree2r^  r_  r`  ra  rb  ru   rc  rd  re  rf  letterrg  r  rE   )rx   r  r   r   rF   rW  \  s$  





<4


4 $

zHolonomicFunction._frobenius   c                    s  |du r	  }n|}t|trt|dkr|d }dnOt|tr1t|dkr1|d |d }n;t|dkrHt|d dkrH|d d }dn$t|dkrct|d dkrc|d d |d d }n	fdd|D S |t }t|jd }|jjjj	}|jj
}|jjj}	|	   fdd|D fd	dtD t|j|d |k rt|d  | D ]tfd
dtD tjd}
|
 q|rوS tfddtD tjd}|r|t|t  7 }|dkr|| S |S )a  
        Finds the power series expansion of given holonomic function about :math:`x_0`.

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

        A list of series might be returned if :math:`x_0` is a regular point with
        multiple roots of the indicial equation.

        Examples
        ========

        >>> from sympy.holonomic.holonomic import HolonomicFunction, DifferentialOperators
        >>> from sympy import QQ
        >>> from sympy import symbols
        >>> x = symbols('x')
        >>> R, Dx = DifferentialOperators(QQ.old_poly_ring(x),'Dx')
        >>> HolonomicFunction(Dx - 1, x, 0, [1]).series()  # e^x
        1 + x + x**2/2 + x**3/6 + x**4/24 + x**5/120 + O(x**6)
        >>> HolonomicFunction(Dx**2 + 1, x, 0, [0, 1]).series(n=8)  # sin(x)
        x - x**3/6 + x**5/120 - x**7/5040 + O(x**8)

        See Also
        ========

        HolonomicFunction.to_sequence
        Nr   r   r   r7   c                    s   g | ]} j |d qS ))_recur)seriesry   r   rE   rF   r}   X  r   z,HolonomicFunction.series.<locals>.<listcomp>c                    r  rE   r	  r   r
  rE   rF   r}   b  r  c                    r  rE   rE   ry   )r1  seqrE   rF   r}   c  r  c                 3   s6    | ]} | d krt |   |   V  qdS rK  )DMFsubsr   )rw   rO   subrE   rF   r   i  s    z+HolonomicFunction.series.<locals>.<genexpr>r  c                 3   s$    | ]\}}|   | V  qd S r?   rE   r   )constantpowerrn   rE   rF   r   p     " )rV  r]   tuplert   r   re  
recurrenceru   rn   r   rs   rl   rS   r   r   r   r!  r   r   r   ro   r3   r   )r_   r   coefficientru   r  r  lr   seq_dmpr   r0  serrE   )	r   r  rw   r1  r_   r  rO   r  rn   rF   r  (  sZ   




zHolonomicFunction.seriesc           	         s  | j dkr| | j  S | jj}| jjj | j j} j	} fddt
dd |D }dt
d|t
d| jj  fdd	tfd
dt|D }t|D ]1\}}| }t|d }d||   kro|kr}n n|||| |  |  }| | 9 }qUt |S )z:
        Computes roots of the Indicial equation.
        r   c                    s,   t  | dd}d| v r|d S dS )NrQ  rR  r   )r.   rr   rZ  )polyroot_all)r   rn   rE   rF   _pole_degree  s   z1HolonomicFunction._indicial.<locals>._pole_degreec                 s   r6  r?   r7  r   rE   rE   rF   r     r9  z.HolonomicFunction._indicial.<locals>.<genexpr>
   r7   c                    s   | j rS  | S r?   )r$  )q)r  infrE   rF   rG     r  z-HolonomicFunction._indicial.<locals>.<lambda>c                 3   s     | ]\}} || V  qd S r?   rE   )rz   rx   r  )degrE   rF   r     s    )r   rU  rq  r   rs   rl   rS   rn   rZ   r[   r   ru   r%  ro   rX  rt   rq   r.   rr   )	r_   
list_coeffr  yr8  r|   rw   rx   r\  rE   )r   r  r  r  rn   rF   rq  x  s&   

zHolonomicFunction._indicialRK4皙?c                 C   s  ddl m} d}t|dsQd}t|}| j|kr#|| |g||dd S |js(t| j}||kr2| }t|| | }	|| g}t|	d D ]}
|	|d |  qEt
| jjj| jjd | jD ]}
|
| jksl|
|v rqt| |
qa|r~|| |||dd S || |||dS )	a  
        Finds numerical value of a holonomic function using numerical methods.
        (RK4 by default). A set of points (real or complex) must be provided
        which will be the path for the numerical integration.

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

        The path should be given as a list :math:`[x_1, x_2, \dots x_n]`. The numerical
        values will be computed at each point in this order
        :math:`x_1 \rightarrow x_2 \rightarrow x_3 \dots \rightarrow x_n`.

        Returns values of the function at :math:`x_1, x_2, \dots x_n` in a list.

        Examples
        ========

        >>> from sympy.holonomic.holonomic import HolonomicFunction, DifferentialOperators
        >>> from sympy import QQ
        >>> from sympy import symbols
        >>> x = symbols('x')
        >>> R, Dx = DifferentialOperators(QQ.old_poly_ring(x),'Dx')

        A straight line on the real axis from (0 to 1)

        >>> r = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]

        Runge-Kutta 4th order on e^x from 0.1 to 1.
        Exact solution at 1 is 2.71828182845905

        >>> HolonomicFunction(Dx - 1, x, 0, [1]).evalf(r)
        [1.10517083333333, 1.22140257085069, 1.34985849706254, 1.49182424008069,
        1.64872063859684, 1.82211796209193, 2.01375162659678, 2.22553956329232,
        2.45960141378007, 2.71827974413517]

        Euler's method for the same

        >>> HolonomicFunction(Dx - 1, x, 0, [1]).evalf(r, method='Euler')
        [1.1, 1.21, 1.331, 1.4641, 1.61051, 1.771561, 1.9487171, 2.14358881,
        2.357947691, 2.5937424601]

        One can also observe that the value obtained using Runge-Kutta 4th order
        is much more accurate than Euler's method.
        r   )_evalfFr   T)methodderivativesr   r7   )sympy.holonomic.numericalr  r   r   r   r   r   r   r   r   r.   r   rl   rS   rr   rs   rn   r=   )r_   pointsr  hr  r  lpr|   r   r   rw   rE   rE   rF   r     s.   .


$
zHolonomicFunction.evalfc                    sV   | j jjj}|| t d\}} fdd| j jD }t||}t||| j	| j
S )z
        Changes only the variable of Holonomic Function, for internal
        purposes. For composition use HolonomicFunction.composition()
        rW   c                    s   g | ]} |  qS rE   )r   r   r   rE   rF   r}     r   z.HolonomicFunction.change_x.<locals>.<listcomp>)r   rl   rS   r   r   rV   rs   rY   r   r   r   )r_   zr   rl   r   rO   rE   r  rF   change_x  s   

zHolonomicFunction.change_xc                    sh   | j | jj}| jjj fdd|D }t|| jj}| j  }|  s,t|S t||| j	S )z-
        Substitute `x + a` for `x`.
        c              	      s(   g | ]} |  qS rE   )rq   rr   r   ry   r   rS   rn   rE   rF   r}     s   ( z-HolonomicFunction.shift_x.<locals>.<listcomp>)
rn   r   rs   rl   rS   rY   r   r   r   r   )r_   r   listaftershiftrO   r   rE   r  rF   rU    s   


zHolonomicFunction.shift_xc              
      sV  |du r	|   }n|}t|tr!t|dkr!|d }|d }d}nst|tr9t|dkr9|d }|d }|d }n[t|dkrVt|d dkrV|d d }|d d }d}n>t|dkrwt|d dkrw|d d }|d d }|d d }n| j||d d}|dd D ]}|| j||d7 }q|S |j}|j | j}	| j}
 j	}|dkr;t
 jj jd |jdd}tj}t|D ]?\}}|dk st|sqt|}|t|k rt|| ttfr||  ||< ||| |	|  7 }q|td	| |	|  7 }qt|ttfr| |	|  }n||	|  }|r,|
dkr(||	|	|
 fgS |fgS |
dkr9||	|	|
 S |S || t|krHtd
t fdd jdd D r_t| | j jd } jd }t| ttfrt|  ||    t|  ||    }nt| ||    t| ||    }d}t
 jj||j}t
 jj||j}|rg }t|| D ]}||k r|r| t|| |	||   |	|	|
 f n|t|| |	|  7 }qt|| dkrqg }g }t!|" D ]}|#t$|| | g||   qt!|" D ]}|#t$|| | g||   q+d|v rJ|%d n| d |ry| t|| |	||   |	|	|
 t&||||	|  |	|	|
 f q|t|| t&||||	|   |	|  7 }q|r|S ||	|  }|
dkr||	|	|
 S |S )a  
        Returns a hypergeometric function (or linear combination of them)
        representing the given holonomic function.

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

        Returns an answer of the form:
        `a_1 \cdot x^{b_1} \cdot{hyper()} + a_2 \cdot x^{b_2} \cdot{hyper()} \dots`

        This is very useful as one can now use ``hyperexpand`` to find the
        symbolic expressions/functions.

        Examples
        ========

        >>> from sympy.holonomic.holonomic import HolonomicFunction, DifferentialOperators
        >>> from sympy import ZZ
        >>> from sympy import symbols
        >>> x = symbols('x')
        >>> R, Dx = DifferentialOperators(ZZ.old_poly_ring(x),'Dx')
        >>> # sin(x)
        >>> HolonomicFunction(Dx**2 + 1, x, 0, [0, 1]).to_hyper()
        x*hyper((), (3/2,), -x**2/4)
        >>> # exp(x)
        >>> HolonomicFunction(Dx - 1, x, 0, [1]).to_hyper()
        hyper((), (), x)

        See Also
        ========

        from_hyper, from_meijerg
        Nr   r7   r   r   )as_listr  r   rR  rT  z+Can't compute sufficient Initial Conditionsc                 3   s    | ]
}| j jjkV  qd S r?   r   ry   rC   rE   rF   r   m  r   z-HolonomicFunction.to_hyper.<locals>.<genexpr>r   )'rV  r]   r  rt   to_hyperre  r  rn   r   ru   r.   rl   rS   rr   rs   r   r   r   ro   r   r   r)   r*   as_exprr   r   r   anyr<   LCr8  r   r   r   rZ  rs  r5   remover%   )r_   r  r  r  r^  r  rO   rw   re  rn   r   mnonzerotermsrx   r   r|   r   arg1arg2	listofsolapbqr1  rE   rC   rF   r    s   #


 

"

<2
.$$

N0
zHolonomicFunction.to_hyperc                 C   s   t |   S )a_  
        Converts a Holonomic Function back to elementary functions.

        Examples
        ========

        >>> from sympy.holonomic.holonomic import HolonomicFunction, DifferentialOperators
        >>> from sympy import ZZ
        >>> from sympy import symbols, S
        >>> x = symbols('x')
        >>> R, Dx = DifferentialOperators(ZZ.old_poly_ring(x),'Dx')
        >>> HolonomicFunction(x**2*Dx**2 + x*Dx + (x**2 - 1), x, 0, [0, S(1)/2]).to_expr()
        besselj(1, x)
        >>> HolonomicFunction((1 + x)*Dx**3 + Dx**2, x, 0, [1, 1, 1]).to_expr()
        x*log(x + 1) + log(x + 1) + 1

        )r4   r  simplifyr   rE   rE   rF   r     s   zHolonomicFunction.to_exprc              	   C   s   d}|du rt | j| jjkrt | j}| jjjj}zt|  | j	|||d}W n t
tfy5   d}Y nw |r?|j|kr?|S | j|dd}t| j| j	||S )a  
        Changes the point `x0` to ``b`` for initial conditions.

        Examples
        ========

        >>> from sympy.holonomic import expr_to_holonomic
        >>> from sympy import symbols, sin, exp
        >>> x = symbols('x')

        >>> expr_to_holonomic(sin(x)).change_ics(1)
        HolonomicFunction((1) + (1)*Dx**2, x, 1, [sin(1), cos(1)])

        >>> expr_to_holonomic(exp(x)).change_ics(2)
        HolonomicFunction((-1) + (1)*Dx, x, 2, [exp(2)])
        TN)rn   r   lenicsrA   F)r  )rt   r   r   ru   rl   rS   rA   expr_to_holonomicr   rn   r;   r<   r   r   r   )r_   r|   r  symbolicr   rO   r   rE   rE   rF   r     s   
zHolonomicFunction.change_icsc                 C   s^   | j dd}tj}|D ]!}t|dkr||d 7 }qt|dkr,||d t|d  7 }q|S )a  
        Returns a linear combination of Meijer G-functions.

        Examples
        ========

        >>> from sympy.holonomic import expr_to_holonomic
        >>> from sympy import sin, cos, hyperexpand, log, symbols
        >>> x = symbols('x')
        >>> hyperexpand(expr_to_holonomic(cos(x) + sin(x)).to_meijerg())
        sin(x) + cos(x)
        >>> hyperexpand(expr_to_holonomic(log(x)).to_meijerg()).simplify()
        log(x)

        See Also
        ========

        to_hyper
        T)r  r7   r   r   )r  r   r   rt   _hyper_to_meijerg)r_   r  rO   rw   rE   rE   rF   
to_meijerg  s   zHolonomicFunction.to_meijergrK  FT)r  FTN)r  r  F)FNr?   )$rf   rg   rh   ri   r   r`   ra   rj   r   r   r   r   r   r   r   re   r   r   r   r   r   r   r   r8  rD  rV  rW  r  rq  r   r  rU  r  r   r   r  rE   rE   rE   rF   r   t  sN    B

 
M ""
@ 
> 
MP
$K
 1
#r   Fc                 C   sf  | j }| j}| jd }|t }tt|d\}}|| }	d}
|D ]}|
|	| 9 }
q$|	d }|}|D ]}||| 9 }q5|
| }t	| }|t
tfv rTt|||S ddd}t|ts|||||j}|sv|d7 }|||||j}|rht|||||S t|trd}|||||j|}|s|d7 }|||||j|}|rt|||||S t|||S )	a  
    Converts a hypergeometric function to holonomic.
    ``func`` is the Hypergeometric Function and ``x0`` is the point at
    which initial conditions are required.

    Examples
    ========

    >>> from sympy.holonomic.holonomic import from_hyper
    >>> from sympy import symbols, hyper, S
    >>> x = symbols('x')
    >>> from_hyper(hyper([], [S(3)/2], x**2/4))
    HolonomicFunction((-x) + (2)*Dx + (x)*Dx**2, x, 1, [sinh(1), -sinh(1) + cosh(1)])
    r   rW   r7   Fc                 S   f   g }t |D ]*}|r| || }n| ||}|jdu s#t|tr& d S || | |} q|S NFr   r   r   rv  r]   r   r   r   simprn   r   ru   r   r   rw   valrE   rE   rF   _find_conditions6  s   
z$from_hyper.<locals>._find_conditionsNr  )r  r  r  atomsr   poprV   r+   r   r4   r   r   r   rD  r]   r%   ru   )funcr   r   r   r|   r  rn   r   rW   xDxr1aixDx_1r2birO   r  r  r   rE   rE   rF   
from_hyper  sD   



r  Tc                 C   s  | j }| j}t| j}t| j}t|}	| jd }
|
t }t	|
|d\}}|| }|d }|d|| |	   }|D ]}||| 9 }q>d}|D ]}||| 9 }qK|| }|sbt|||
S t| }|ttfv rtt|||
S d	dd}t|ts|||||j}|s|d7 }|||||j}|rt|||
||S t|trd}|||||j|}|s|d7 }|||||j|}|rt|||
||S t|||
S )
a  
    Converts a Meijer G-function to Holonomic.
    ``func`` is the G-Function and ``x0`` is the point at
    which initial conditions are required.

    Examples
    ========

    >>> from sympy.holonomic.holonomic import from_meijerg
    >>> from sympy import symbols, meijerg, S
    >>> x = symbols('x')
    >>> from_meijerg(meijerg(([], []), ([S(1)/2], [0]), x**2/4))
    HolonomicFunction((1) + (1)*Dx**2, x, 0, [0, 1/sqrt(pi)])
    r   rW   r7   r   Fc                 S   r  r  r  r  rE   rE   rF   r    s   
z&from_meijerg.<locals>._find_conditionsNr  )r  r  rt   anbmr  r  r   r  rV   r   r   rD  r4   r   r   r]   r&   ru   )r  r   r   r   rA   r   r|   r   r  r   r  rn   r   rW   r  xDx1r  r  r  r  rO   r  r  r   rE   rE   rF   from_meijerg\  sN   





r  x_1N)_mytypec              	   C   s  t | } | j}|st|dkr| }ntd||v r!|| t|}|du r?| tr1t	}nt
}t|dkr?||  }t| ||||||d}	|	rN|	S ts[|ai att|d n|tkri|ai att|d | jr| |t}
t|
t}|tv rt| }|d d |}n>t| |d|d}|st|r||_|s|s||_|S |s|jj}t| |||}|s|d7 }t| |||}|rt|j|||S |s|s|| jd }|r||_||_|S |s|jj}t| |||}|s|d7 }t| |||}|r|| jd ||S | j}| j}
t |d |d|d	}|
t!u r1t"dt|D ]}|t || |d|d	7 }q n(|
t#u rNt"dt|D ]}|t || |d|d	9 }q=n|
t$u rY||d  }||_|sat|rg||_|sm|so|S |jru|S |s||jj}|j%|r|& }t|}t|dkr||d  t'j(kr|d }| || |  }t||||}d
d t)|D }||i}t|j|||S t| |||}|s|d7 }t| |||}|rt|j|||S )a  
    Converts a function or an expression to a holonomic function.

    Parameters
    ==========

    func:
        The expression to be converted.
    x:
        variable for the function.
    x0:
        point at which initial condition must be computed.
    y0:
        One can optionally provide initial condition if the method
        is not able to do it automatically.
    lenics:
        Number of terms in the initial condition. By default it is
        equal to the order of the annihilator.
    domain:
        Ground domain for the polynomials in ``x`` appearing as coefficients
        in the annihilator.
    initcond:
        Set it false if you do not want the initial conditions to be computed.

    Examples
    ========

    >>> from sympy.holonomic.holonomic import expr_to_holonomic
    >>> from sympy import sin, exp, symbols
    >>> x = symbols('x')
    >>> expr_to_holonomic(sin(x))
    HolonomicFunction((1) + (1)*Dx**2, x, 0, [0, 1])
    >>> expr_to_holonomic(exp(x))
    HolonomicFunction((-1) + (1)*Dx, x, 0, [1])

    See Also
    ========

    sympy.integrals.meijerint._rewrite1, _convert_poly_rat_alg, _create_table
    r7   z%Specify the variable for the functionNr   )r   r   r  rA   r   )rA   Fr   rA   )rn   r   rA   c                 S   r   rE   r   r   rE   rE   rF   r}   H	  r   z%expr_to_holonomic.<locals>.<listcomp>)*r   free_symbolsrt   r  
ValueErrorr  r   r"  r   r,   r+   r   _convert_poly_rat_alg_lookup_tabledomain_for_table_create_tableis_Functionr   r  r  r  _convert_meijerintr   r   r   r   ru   r  r   rD  r  r  r  r   r   r   r   r   rq  r   r   ro   )r  rn   r   r   r  rA   r   syms
extra_symssolpolyftr  rO   r   r  rw   rD   gsingular_icsrE   rE   rF   r    s   )






"r  c                 C   sv  g }g }|j }| }|tj}g }t| D ]=\}	}
t|
|jr,||	|

  nt|
|js=||t|
 n||
 |||	   |||	   q|D ]}	|	|}qW|rd| }|	|
 }t|D ]
\}	}
|
| ||	< qo||d  |d   
 }|D ]}	|	|}q|	|
 }t|D ]\}	}
|
| }|| |  
 ||	< qt||S )z'
    Normalize a given annihilator
    r   )rS   r   rq   r   r   ro   r]   rp   r   r   r   r   numerdenomlcmgcdrY   )list_ofrl   r   numr  rS   r   	lcm_denomlist_of_coeffrw   rx   	gcd_numerfrac_ansrE   rE   rF   r   V	  s:   
 
r   c                 C   sh   g }t | d }|t| d | t| dd D ]\}}|t||| |   q|| |  |S )a*  
    Let a differential equation a0(x)y(x) + a1(x)y'(x) + ... = 0
    where a0, a1,... are polynomials or rational functions. The function
    returns b0, b1, b2... such that the differential equation
    b0(x)y(x) + b1(x)y'(x) +... = 0 is formed after differentiating the
    former equation.
    r7   r   N)rt   r   r#  ro   )rs   r   rO   r   rw   rx   rE   rE   rF   r  	  s   	r  c           
      C   s   | j }| j}tdd |D rt| S | jd }dd |D }d}tjf}dd |D }tj}|D ]}	|t|	 }q1|D ]}	|t|	 }q<|t	|||||  S )z(
    Converts a `hyper` to meijerg.
    c                 s   s$    | ]}|d kot ||kV  qdS rK  rn  ry   rE   rE   rF   r   	  r  z$_hyper_to_meijerg.<locals>.<genexpr>r   c                 s       | ]}d | V  qdS rm  rE   ry   rE   rE   rF   r   	  r9  rE   c                 s   r  rm  rE   ry   rE   rE   rF   r   	  r9  )
r  r  r  r4   r  r   r   r   r$   r&   )
r  r  r  r  r  anpr  bmqr1  rw   rE   rE   rF   r  	  s   
r  c                 C   s`   t | t |krdd t| |D |t | d  }|S dd t| |D | t |d  }|S )zvTakes polynomial sequences of two annihilators a and b and returns
    the list of polynomials of sum of a and b.
    c                 S   r   rE   rE   r   rE   rE   rF   r}   	  r   z_add_lists.<locals>.<listcomp>Nc                 S   r   rE   rE   r   rE   rE   rF   r}   	  r   )rt   r   )list1list2rO   rE   rE   rF   r   	  s
   $$r   c                    sX  | j | js|  dkr| jS | j }|j g | j}|jj}| }|j	D ]}t
||jjjr:||  q&t| k sG|t|krI|S  fddt D }|dtt|  }t|  D ];}	d}
t||D ]'\ }t|| j}t|dds|    S t
|ttfr| }|
 | 7 }
qo||
 t||}qf||t|d  S )zy
    Tries to find more initial conditions by substituting the initial
    value point in the differential equation.
    Tc                    r  rE   rE   ry   r   rs   rE   rF   r}   	  s    z_extend_y0.<locals>.<listcomp>Nr   rv  )r   r   r   r   r   ru   rl   rS   r   rs   r]   rp   r   r   r   rt   r   r%  r   r  getattrr)   r*   r  r  )	Holonomicr   r   r   r   r   rx   list_redr   r   rO   r|   rD   rE   r  rF   r   	  s<   

r   c                 C   s\   t | ts	|  S || }|| }| |  ||   }|d }|| | fS rl  )r]   r-   r   r  r  r   )fracr   r   r  sol_num	sol_denomrE   rE   rF   r#  	  s   


r#  c           
      C   s   t | ts| S | j}| j}tj}tj}|rddlm} tt	|D ]\}}	|r/t
|	|j}	||	||  7 }q!tt	|D ]\}}	|rLt
|	|j}	||	||  7 }q>t |ttfr`| }t |ttfrk| }|| S )Nr   )mp)r]   r-   r  denr   r   mpmathr  ro   reversedr   
_to_mpmathprecr)   r*   r  )
r  r   mpmr   r  sol_psol_qr  rw   rx   rE   rE   rF   r   
  s*   
r  c                 C   s  |   }|s|  }nd}|s4|s4|  \}	}
|	  r1|
jr1t|
tr't|
}
|
j|
j}}d}nd}nd}|s>|s>|s>dS |	|}t
|d\}}| |sWt||d| gS |r| | | | }t|j|jdd}||}|du r|dkr|r||  }tt|D ]\}}|dkrqtt||d }|} t|D ]\}}t|ttfr| ||< q|t|i}n|r|  \}}|| | |||  |||  }t|j|jdd}nv|rV|||  | d }t|||	j}||}|du rV|dkrV|rV|du s|dkrV||	 }tt|D ]#\}}|dkr*qt|ttfr6| }t||
 }t||
 } t|ttfrO| }|t|gi}|s\|sct||||S |si|j}||rt||| }t|}t |dkr||d  tj!kr|d }| || |  }t"||||}dd	 t|D }||i}t||||S t"| |||}|s|d7 }t"| |||}|rt||||S )
zO
    Converts polynomials, rationals and algebraic functions to holonomic.
    TFNrW   r   r   r7   c                 S   r   rE   r   r   rE   rE   rF   r}   }
  r   z)_convert_poly_rat_alg.<locals>.<listcomp>)#is_polynomialis_rational_functionas_base_expr   r]   r   r5   r   r  r   rV   r"  r   r   r   rs   rl   r   rq   r   ro   r   r   r)   r*   r  r   as_numer_denomrD  r   ru   rq  rt   r   r  )r  rn   r   r   r  rA   r   ispolyisratbasepolyratexpr  r   is_algr   r   rW   rO   r   r  rw   rx   r0  indicialr   r  rD   r  r  r  rE   rE   rF   r  
  s   




(

"r  c                    s   t | }|r|\ }}}nd S  fdd|D }| }	|	d kr(|	d ntjfdd|D }
dd |D }fdd}||d |
d \}}|d | t|||d	 }tdt|D ]}||| |
| \}}||| | t|||d	 7 }q`|S )
Nc                    s   g | ]} |d   qS r  rE   ry   )facrE   rF   r}   
  r   z&_convert_meijerint.<locals>.<listcomp>r   r7   c                    s   g | ]} |d   qS )r7   rE   ry   )r  rE   rF   r}   
  r   c                 S   rI  )r   rE   ry   rE   rE   rF   r}   
  r~   c                    s   | j d }|tr|tt}|jdd}t|d }|| }| }|d kr/|d nt	j
}||   fdd| j d d D } fdd| j d d D } fd	d| j d d D }	 fd
d| j d d D }
|   t||f|	|
f|fS )Nr   F)r  r   r7   c                 3       | ]}|  V  qd S r?   rE   ry   rC   rE   rF   r   
  r9  z5_convert_meijerint.<locals>._shift.<locals>.<genexpr>c                 3   r  r?   rE   ry   rC   rE   rF   r   
  r9  c                 3   r  r?   rE   ry   rC   rE   rF   r   
  r9  c                 3   r  r?   rE   ry   rC   rE   rF   r   
  r9  )r  r"  r	   r   r   r   collectr   r  r   r   r&   )r  r  r  dr|   r   r  r  r  r  r  ri  rC   rF   _shift
  s   

z"_convert_meijerint.<locals>._shiftr  )r'   	_rewrite1r  r   r   r  r   rt   )r  rn   r   rA   r  por  r   fac_listr  po_listG_listr  r0  r  rO   rw   rE   )r  r  rn   rF   r  
  s     r  c              	      s   d fdd	}| t}t|d\}}|tt|d d tdddg |tt|d d tdddg |tt|d tdd |tt|t|d   tdddg |ttdt | |d  tdddtt	 g |t
tdt | |d  tdddtt	 g |ttdt | |d  tdddtt	 g |tt|d d tdddg |tt|d d tdddg |tttd|  t|d   t |ttt| d|d   t|d	   t |ttt| d|d   t|d	   t |ttt | d|d   t|d	   t d
S )zi
    Creates the look-up table. For a similar implementation
    see meijerint._create_lookup_table.
    r   rE   c                    s*     t| tg | t||||f dS )z2
        Adds a formula in the dictionary
        N)r  r  r  r   r   )formular   argr   r   tablerE   rF   add
  s   
z_create_table.<locals>.addrW   r   r7   r   N)r   rE   )r   r  rV   r   r   r   r   r!   r   r
   r"   r#   r   r   r   r    r   r   )r  rA   r  r   r   rW   rE   r  rF   r  
  s    
  $000  $,,2r  c                 C   sf   g }t |D ]*}| ||}t|trt| ||}|jdu s#t|tr& d S || | |} q|S r  )r   r   r]   r   r2   rv  r   r   )r  rn   r   ru   r   rw   r  rE   rE   rF   r  
  s   

r  )r   F)Nr   NNNTr  r  )tri   
sympy.corer   r   r   sympy.core.numbersr   r   r   r   r	   r
   r   r   sympy.core.singletonr   sympy.core.sortingr   sympy.core.symbolr   r   sympy.core.sympifyr   (sympy.functions.combinatorial.factorialsr   r   r   &sympy.functions.elementary.exponentialr   r   r   %sympy.functions.elementary.hyperbolicr   r   (sympy.functions.elementary.miscellaneousr   (sympy.functions.elementary.trigonometricr   r   r   'sympy.functions.special.error_functionsr   r   r    r!   r"   r#   'sympy.functions.special.gamma_functionsr$   sympy.functions.special.hyperr%   r&   sympy.integralsr'   sympy.matricesr(   sympy.polys.ringsr)   sympy.polys.fieldsr*   sympy.polys.domainsr+   r,   sympy.polys.polyclassesr-   sympy.polys.polyrootsr.   sympy.polys.polytoolsr/   sympy.polys.matricesr0   sympy.printingr1   sympy.series.limitsr2   sympy.series.orderr3   sympy.simplify.hyperexpandr4   sympy.simplify.simplifyr5   sympy.solvers.solversr6   r  r8   r9   r:   holonomicerrorsr;   r<   r=   r>   rP   rV   rQ   rY   r   r  r  r  r  r  sympy.integrals.meijerintr  r  r   r  r  r   r   r#  r  r  r  r  r  rE   rE   rE   rF   <module>   s    ( 
&D W             
(MP
 
%9)
j.%