(eq, func, order, match)
r"""
    Gives a power series solution to a second order homogeneous differential
    equation with polynomial coefficients at a regular point. A second order
    homogenous differential equation is of the form

    .. math :: P(x)\frac{d^2y}{dx^2} + Q(x)\frac{dy}{dx} + R(x) = 0

    A point is said to regular singular at `x0` if `x - x0\frac{Q(x)}{P(x)}`
    and `(x - x0)^{2}\frac{R(x)}{P(x)}` are analytic at `x0`. For simplicity
    `P(x)`, `Q(x)` and `R(x)` are assumed to be polynomials. The algorithm for
    finding the power series solutions is:

    1.  Try expressing `(x - x0)P(x)` and `((x - x0)^{2})Q(x)` as power series
        solutions about x0. Find `p0` and `q0` which are the constants of the
        power series expansions.
    2.  Solve the indicial equation `f(m) = m(m - 1) + m*p0 + q0`, to obtain the
        roots `m1` and `m2` of the indicial equation.
    3.  If `m1 - m2` is a non integer there exists two series solutions. If
        `m1 = m2`, there exists only one solution. If `m1 - m2` is an integer,
        then the existence of one solution is confirmed. The other solution may
        or may not exist.

    The power series solution is of the form `x^{m}\sum_{n=0}^\infty anx^n`. The
    coefficients are determined by the following recurrence relation.
    `an = -\frac{\sum_{k=0}^{n-1} q_{n-k} + (m + k)p_{n-k}}{f(m + n)}`. For the case
    in which `m1 - m2` is an integer, it can be seen from the recurrence relation
    that for the lower root `m`, when `n` equals the difference of both the
    roots, the denominator becomes zero. So if the numerator is not equal to zero,
    a second series solution exists.


    Examples
    ========

    >>> from sympy import dsolve, Function, pprint
    >>> from sympy.abc import x, y
    >>> f = Function("f")
    >>> eq = x*(f(x).diff(x, 2)) + 2*(f(x).diff(x)) + x*f(x)
    >>> pprint(dsolve(eq))
                                  /    6    4    2    \
                                  |   x    x    x     |
              /  4    2    \   C1*|- --- + -- - -- + 1|
              | x    x     |      \  720   24   2     /    / 6\
    f(x) = C2*|--- - -- + 1| + ------------------------ + O\x /
              \120   6     /              x


    References
    ==========
    - George E. Simmons, "Differential Equations with Applications and
      Historical Notes", p.p 176 - 184
r"""
    Gives a power series solution to a second order homogeneous differential
    equation with polynomial coefficients at a regular point. A second order
    homogenous differential equation is of the form
r Gives a power series solution to a second order homogeneous differential equation with polynomial coefficients at a regular point . A second order homogenous differential equation is of the form
def ode_2nd_power_series_regular(eq, func, order, match):
    r"""
    Gives a power series solution to a second order homogeneous differential
    equation with polynomial coefficients at a regular point. A second order
    homogenous differential equation is of the form

    .. math :: P(x)\frac{d^2y}{dx^2} + Q(x)\frac{dy}{dx} + R(x) = 0

    A point is said to regular singular at `x0` if `x - x0\frac{Q(x)}{P(x)}`
    and `(x - x0)^{2}\frac{R(x)}{P(x)}` are analytic at `x0`. For simplicity
    `P(x)`, `Q(x)` and `R(x)` are assumed to be polynomials. The algorithm for
    finding the power series solutions is:

    1.  Try expressing `(x - x0)P(x)` and `((x - x0)^{2})Q(x)` as power series
        solutions about x0. Find `p0` and `q0` which are the constants of the
        power series expansions.
    2.  Solve the indicial equation `f(m) = m(m - 1) + m*p0 + q0`, to obtain the
        roots `m1` and `m2` of the indicial equation.
    3.  If `m1 - m2` is a non integer there exists two series solutions. If
        `m1 = m2`, there exists only one solution. If `m1 - m2` is an integer,
        then the existence of one solution is confirmed. The other solution may
        or may not exist.

    The power series solution is of the form `x^{m}\sum_{n=0}^\infty anx^n`. The
    coefficients are determined by the following recurrence relation.
    `an = -\frac{\sum_{k=0}^{n-1} q_{n-k} + (m + k)p_{n-k}}{f(m + n)}`. For the case
    in which `m1 - m2` is an integer, it can be seen from the recurrence relation
    that for the lower root `m`, when `n` equals the difference of both the
    roots, the denominator becomes zero. So if the numerator is not equal to zero,
    a second series solution exists.


    Examples
    ========

    >>> from sympy import dsolve, Function, pprint
    >>> from sympy.abc import x, y
    >>> f = Function("f")
    >>> eq = x*(f(x).diff(x, 2)) + 2*(f(x).diff(x)) + x*f(x)
    >>> pprint(dsolve(eq))
                                  /    6    4    2    \
                                  |   x    x    x     |
              /  4    2    \   C1*|- --- + -- - -- + 1|
              | x    x     |      \  720   24   2     /    / 6\
    f(x) = C2*|--- - -- + 1| + ------------------------ + O\x /
              \120   6     /              x


    References
    ==========
    - George E. Simmons, "Differential Equations with Applications and
      Historical Notes", p.p 176 - 184

    """
    x = func.args[0]
    f = func.func
    C0, C1 = get_numbered_constants(eq, num=2)
    n = Dummy("n")
    m = Dummy("m")  # for solving the indicial equation
    s = Wild("s")
    k = Wild("k", exclude=[x])
    x0 = match.get('x0')
    terms = match.get('terms', 5)
    p = match['p']
    q = match['q']

    # Generating the indicial equation
    indicial = []
    for term in [p, q]:
        if not term.has(x):
            indicial.append(term)
        else:
            term = series(term, n=1, x0=x0)
            if isinstance(term, Order):
                indicial.append(S(0))
            else:
                for arg in term.args:
                    if not arg.has(x):
                        indicial.append(arg)
                        break

    p0, q0 = indicial
    sollist = solve(m*(m - 1) + m*p0 + q0, m)
    if sollist and isinstance(sollist, list) and all(
        [sol.is_real for sol in sollist]):
        serdict1 = {}
        serdict2 = {}
        if len(sollist) == 1:
            # Only one series solution exists in this case.
            m1 = m2 = sollist.pop()
            if terms-m1-1 <= 0:
              return Eq(f(x), Order(terms))
            serdict1 = _frobenius(terms-m1-1, m1, p0, q0, p, q, x0, x, C0)

        else:
            m1 = sollist[0]
            m2 = sollist[1]
            if m1 < m2:
                m1, m2 = m2, m1
            # Irrespective of whether m1 - m2 is an integer or not, one
            # Frobenius series solution exists.
            serdict1 = _frobenius(terms-m1-1, m1, p0, q0, p, q, x0, x, C0)
            if not (m1 - m2).is_integer:
                # Second frobenius series solution exists.
                serdict2 = _frobenius(terms-m2-1, m2, p0, q0, p, q, x0, x, C1)
            else:
                # Check if second frobenius series solution exists.
                serdict2 = _frobenius(terms-m2-1, m2, p0, q0, p, q, x0, x, C1, check=m1)

        if serdict1:
            finalseries1 = C0
            for key in serdict1:
                power = int(key.name[1:])
                finalseries1 += serdict1[key]*(x - x0)**power
            finalseries1 = (x - x0)**m1*finalseries1
            finalseries2 = S(0)
            if serdict2:
                for key in serdict2:
                    power = int(key.name[1:])
                    finalseries2 += serdict2[key]*(x - x0)**power
                finalseries2 += C1
                finalseries2 = (x - x0)**m2*finalseries2
            return Eq(f(x), collect(finalseries1 + finalseries2,
                [C0, C1]) + Order(x**terms))
def ode_2nd_power_series_regular ( eq , func , order , match ) : x = func . args [ 0 ] f = func . func C0 , C1 = get_numbered_constants ( eq , num = 2 ) n = Dummy ( "n" ) m = Dummy ( "m" ) # for solving the indicial equation s = Wild ( "s" ) k = Wild ( "k" , exclude = [ x ] ) x0 = match . get ( 'x0' ) terms = match . get ( 'terms' , 5 ) p = match [ 'p' ] q = match [ 'q' ] # Generating the indicial equation indicial = [ ] for term in [ p , q ] : if not term . has ( x ) : indicial . append ( term ) else : term = series ( term , n = 1 , x0 = x0 ) if isinstance ( term , Order ) : indicial . append ( S ( 0 ) ) else : for arg in term . args : if not arg . has ( x ) : indicial . append ( arg ) break p0 , q0 = indicial sollist = solve ( m * ( m - 1 ) + m * p0 + q0 , m ) if sollist and isinstance ( sollist , list ) and all ( [ sol . is_real for sol in sollist ] ) : serdict1 = { } serdict2 = { } if len ( sollist ) == 1 : # Only one series solution exists in this case. m1 = m2 = sollist . pop ( ) if terms - m1 - 1 <= 0 : return Eq ( f ( x ) , Order ( terms ) ) serdict1 = _frobenius ( terms - m1 - 1 , m1 , p0 , q0 , p , q , x0 , x , C0 ) else : m1 = sollist [ 0 ] m2 = sollist [ 1 ] if m1 < m2 : m1 , m2 = m2 , m1 # Irrespective of whether m1 - m2 is an integer or not, one # Frobenius series solution exists. serdict1 = _frobenius ( terms - m1 - 1 , m1 , p0 , q0 , p , q , x0 , x , C0 ) if not ( m1 - m2 ) . is_integer : # Second frobenius series solution exists. serdict2 = _frobenius ( terms - m2 - 1 , m2 , p0 , q0 , p , q , x0 , x , C1 ) else : # Check if second frobenius series solution exists. serdict2 = _frobenius ( terms - m2 - 1 , m2 , p0 , q0 , p , q , x0 , x , C1 , check = m1 ) if serdict1 : finalseries1 = C0 for key in serdict1 : power = int ( key . name [ 1 : ] ) finalseries1 += serdict1 [ key ] * ( x - x0 ) ** power finalseries1 = ( x - x0 ) ** m1 * finalseries1 finalseries2 = S ( 0 ) if serdict2 : for key in serdict2 : power = int ( key . name [ 1 : ] ) finalseries2 += serdict2 [ key ] * ( x - x0 ) ** power finalseries2 += C1 finalseries2 = ( x - x0 ) ** m2 * finalseries2 return Eq ( f ( x ) , collect ( finalseries1 + finalseries2 , [ C0 , C1 ] ) + Order ( x ** terms ) )