(match, comp=False)
r"""
    The aim of the fourth heuristic is to find the function `\chi(x, y)`
    that satisifies the PDE `\frac{d\chi}{dx} + h\frac{d\chi}{dx}
    - \frac{\partial h}{\partial y}\chi = 0`.

    This assumes `\chi` to be a bivariate polynomial in `x` and `y`. By intution,
    `h` should be a rational function in `x` and `y`. The method used here is
    to substitute a general binomial for `\chi` up to a certain maximum degree
    is reached. The coefficients of the polynomials, are calculated by by collecting
    terms of the same order in `x` and `y`.

    After finding `\chi`, the next step is to use `\eta = \xi*h + \chi`, to
    determine `\xi` and `\eta`. This can be done by dividing `\chi` by `h`
    which would give `-\xi` as the quotient and `\eta` as the remainder.


    References
    ==========
    - E.S Cheb-Terrab, L.G.S Duarte and L.A,C.P da Mota, Computer Algebra
      Solving of First Order ODEs Using Symmetry Methods, pp. 8
r"""
    The aim of the fourth heuristic is to find the function `\chi(x, y)`
    that satisifies the PDE `\frac{d\chi}{dx} + h\frac{d\chi}{dx}
    - \frac{\partial h}{\partial y}\chi = 0`.
r The aim of the fourth heuristic is to find the function \ chi ( x y ) that satisifies the PDE \ frac { d \ chi } { dx } + h \ frac { d \ chi } { dx } - \ frac { \ partial h } { \ partial y } \ chi = 0 .
def lie_heuristic_chi(match, comp=False):
    r"""
    The aim of the fourth heuristic is to find the function `\chi(x, y)`
    that satisifies the PDE `\frac{d\chi}{dx} + h\frac{d\chi}{dx}
    - \frac{\partial h}{\partial y}\chi = 0`.

    This assumes `\chi` to be a bivariate polynomial in `x` and `y`. By intution,
    `h` should be a rational function in `x` and `y`. The method used here is
    to substitute a general binomial for `\chi` up to a certain maximum degree
    is reached. The coefficients of the polynomials, are calculated by by collecting
    terms of the same order in `x` and `y`.

    After finding `\chi`, the next step is to use `\eta = \xi*h + \chi`, to
    determine `\xi` and `\eta`. This can be done by dividing `\chi` by `h`
    which would give `-\xi` as the quotient and `\eta` as the remainder.


    References
    ==========
    - E.S Cheb-Terrab, L.G.S Duarte and L.A,C.P da Mota, Computer Algebra
      Solving of First Order ODEs Using Symmetry Methods, pp. 8

    """

    h = match['h']
    hx = match['hx']
    hy = match['hy']
    func = match['func']
    x = func.args[0]
    y = match['y']
    xi = Function('xi')(x, func)
    eta = Function('eta')(x, func)

    if h.is_rational_function():
        schi, schix, schiy = symbols("schi, schix, schiy")
        cpde = schix + h*schiy - hy*schi
        num, denom = cancel(cpde).as_numer_denom()
        deg = Poly(num, x, y).total_degree()

        chi = Function('chi')(x, y)
        chix = chi.diff(x)
        chiy = chi.diff(y)
        cpde = chix + h*chiy - hy*chi
        chieq = Symbol("chi")
        for i in range(1, deg + 1):
            chieq += Add(*[
                Symbol("chi_" + str(power) + "_" + str(i - power))*x**power*y**(i - power)
                for power in range(i + 1)])
            cnum, cden = cancel(cpde.subs({chi : chieq}).doit()).as_numer_denom()
            cnum = expand(cnum)
            if cnum.is_polynomial(x, y) and cnum.is_Add:
                cpoly = Poly(cnum, x, y).as_dict()
                if cpoly:
                    solsyms = chieq.free_symbols - set([x, y])
                    soldict = solve(cpoly.values(), *solsyms)
                    if isinstance(soldict, list):
                        soldict = soldict[0]
                    if any(x for x in soldict.values()):
                        chieq = chieq.subs(soldict)
                        dict_ = dict((sym, 1) for sym in solsyms)
                        chieq = chieq.subs(dict_)
                        # After finding chi, the main aim is to find out
                        # eta, xi by the equation eta = xi*h + chi
                        # One method to set xi, would be rearranging it to
                        # (eta/h) - xi = (chi/h). This would mean dividing
                        # chi by h would give -xi as the quotient and eta
                        # as the remainder. Thanks to Sean Vig for suggesting
                        # this method.
                        xic, etac = div(chieq, h)
                        inf = {eta: etac.subs(y, func), xi: -xic.subs(y, func)}
                        return [inf]
def lie_heuristic_chi ( match , comp = False ) : h = match [ 'h' ] hx = match [ 'hx' ] hy = match [ 'hy' ] func = match [ 'func' ] x = func . args [ 0 ] y = match [ 'y' ] xi = Function ( 'xi' ) ( x , func ) eta = Function ( 'eta' ) ( x , func ) if h . is_rational_function ( ) : schi , schix , schiy = symbols ( "schi, schix, schiy" ) cpde = schix + h * schiy - hy * schi num , denom = cancel ( cpde ) . as_numer_denom ( ) deg = Poly ( num , x , y ) . total_degree ( ) chi = Function ( 'chi' ) ( x , y ) chix = chi . diff ( x ) chiy = chi . diff ( y ) cpde = chix + h * chiy - hy * chi chieq = Symbol ( "chi" ) for i in range ( 1 , deg + 1 ) : chieq += Add ( * [ Symbol ( "chi_" + str ( power ) + "_" + str ( i - power ) ) * x ** power * y ** ( i - power ) for power in range ( i + 1 ) ] ) cnum , cden = cancel ( cpde . subs ( { chi : chieq } ) . doit ( ) ) . as_numer_denom ( ) cnum = expand ( cnum ) if cnum . is_polynomial ( x , y ) and cnum . is_Add : cpoly = Poly ( cnum , x , y ) . as_dict ( ) if cpoly : solsyms = chieq . free_symbols - set ( [ x , y ] ) soldict = solve ( cpoly . values ( ) , * solsyms ) if isinstance ( soldict , list ) : soldict = soldict [ 0 ] if any ( x for x in soldict . values ( ) ) : chieq = chieq . subs ( soldict ) dict_ = dict ( ( sym , 1 ) for sym in solsyms ) chieq = chieq . subs ( dict_ ) # After finding chi, the main aim is to find out # eta, xi by the equation eta = xi*h + chi # One method to set xi, would be rearranging it to # (eta/h) - xi = (chi/h). This would mean dividing # chi by h would give -xi as the quotient and eta # as the remainder. Thanks to Sean Vig for suggesting # this method. xic , etac = div ( chieq , h ) inf = { eta : etac . subs ( y , func ) , xi : - xic . subs ( y , func ) } return [ inf ]