(fa, fd, wa, wd, DE, c1=None)
return (Q*N, Q*M, v)
Parametric logarithmic derivative heuristic.

    Given a derivation D on k[t], f in k(t), and a hyperexponential monomial
    theta over k(t), raises either NotImplementedError, in which case the
    heuristic failed, or returns None, in which case it has proven that no
    solution exists, or returns a solution (n, m, v) of the equation
    n*f == Dv/v + m*Dtheta/theta, with v in k(t)* and n, m in ZZ with n != 0.

    If this heuristic fails, the structure theorem approach will need to be
    used.

    The argument w == Dtheta/theta
Parametric logarithmic derivative heuristic.
Parametric logarithmic derivative heuristic .
def parametric_log_deriv_heu(fa, fd, wa, wd, DE, c1=None):
    """
    Parametric logarithmic derivative heuristic.

    Given a derivation D on k[t], f in k(t), and a hyperexponential monomial
    theta over k(t), raises either NotImplementedError, in which case the
    heuristic failed, or returns None, in which case it has proven that no
    solution exists, or returns a solution (n, m, v) of the equation
    n*f == Dv/v + m*Dtheta/theta, with v in k(t)* and n, m in ZZ with n != 0.

    If this heuristic fails, the structure theorem approach will need to be
    used.

    The argument w == Dtheta/theta
    """
    # TODO: finish writing this and write tests
    c1 = c1 or Dummy('c1')

    p, a = fa.div(fd)
    q, b = wa.div(wd)

    B = max(0, derivation(DE.t, DE).degree(DE.t) - 1)
    C = max(p.degree(DE.t), q.degree(DE.t))

    if q.degree(DE.t) > B:
        eqs = [p.nth(i) - c1*q.nth(i) for i in range(B + 1, C + 1)]
        s = solve(eqs, c1)
        if not s or not s[c1].is_Rational:
            # deg(q) > B, no solution for c.
            return None

        N, M = s[c1].as_numer_denom()  # N and M are integers
        N, M = Poly(N, DE.t), Poly(M, DE.t)

        nfmwa = N*fa*wd - M*wa*fd
        nfmwd = fd*wd
        Qv = is_log_deriv_k_t_radical_in_field(N*fa*wd - M*wa*fd, fd*wd, DE,
            'auto')
        if Qv is None:
            # (N*f - M*w) is not the logarithmic derivative of a k(t)-radical.
            return None

        Q, e, v = Qv
        if e != 1:
            return None

        if Q.is_zero or v.is_zero:
            # Q == 0 or v == 0.
            return None

        return (Q*N, Q*M, v)

    if p.degree(DE.t) > B:
        return None

    c = lcm(fd.as_poly(DE.t).LC(), wd.as_poly(DE.t).LC())
    l = fd.monic().lcm(wd.monic())*Poly(c, DE.t)
    ln, ls = splitfactor(l, DE)
    z = ls*ln.gcd(ln.diff(DE.t))

    if not z.has(DE.t):
        raise NotImplementedError("parametric_log_deriv_heu() "
            "heuristic failed: z in k.")

    u1, r1 = (fa*l.quo(fd)).div(z)  # (l*f).div(z)
    u2, r2 = (wa*l.quo(wd)).div(z)  # (l*w).div(z)

    eqs = [r1.nth(i) - c1*r2.nth(i) for i in range(z.degree(DE.t))]
    s = solve(eqs, c1)
    if not s or not s[c1].is_Rational:
        # deg(q) <= B, no solution for c.
        return None

    M, N = s[c1].as_numer_denom()

    nfmwa = N.as_poly(DE.t)*fa*wd - M.as_poly(DE.t)*wa*fd
    nfmwd = fd*wd
    Qv = is_log_deriv_k_t_radical_in_field(nfmwa, nfmwd, DE)
    if Qv is None:
        # (N*f - M*w) is not the logarithmic derivative of a k(t)-radical.
        return None

    Q, v = Qv

    if Q.is_zero or v.is_zero:
        # Q == 0 or v == 0.
        return None

    return (Q*N, Q*M, v)
def parametric_log_deriv_heu ( fa , fd , wa , wd , DE , c1 = None ) : # TODO: finish writing this and write tests c1 = c1 or Dummy ( 'c1' ) p , a = fa . div ( fd ) q , b = wa . div ( wd ) B = max ( 0 , derivation ( DE . t , DE ) . degree ( DE . t ) - 1 ) C = max ( p . degree ( DE . t ) , q . degree ( DE . t ) ) if q . degree ( DE . t ) > B : eqs = [ p . nth ( i ) - c1 * q . nth ( i ) for i in range ( B + 1 , C + 1 ) ] s = solve ( eqs , c1 ) if not s or not s [ c1 ] . is_Rational : # deg(q) > B, no solution for c. return None N , M = s [ c1 ] . as_numer_denom ( ) # N and M are integers N , M = Poly ( N , DE . t ) , Poly ( M , DE . t ) nfmwa = N * fa * wd - M * wa * fd nfmwd = fd * wd Qv = is_log_deriv_k_t_radical_in_field ( N * fa * wd - M * wa * fd , fd * wd , DE , 'auto' ) if Qv is None : # (N*f - M*w) is not the logarithmic derivative of a k(t)-radical. return None Q , e , v = Qv if e != 1 : return None if Q . is_zero or v . is_zero : # Q == 0 or v == 0. return None return ( Q * N , Q * M , v ) if p . degree ( DE . t ) > B : return None c = lcm ( fd . as_poly ( DE . t ) . LC ( ) , wd . as_poly ( DE . t ) . LC ( ) ) l = fd . monic ( ) . lcm ( wd . monic ( ) ) * Poly ( c , DE . t ) ln , ls = splitfactor ( l , DE ) z = ls * ln . gcd ( ln . diff ( DE . t ) ) if not z . has ( DE . t ) : raise NotImplementedError ( "parametric_log_deriv_heu() " "heuristic failed: z in k." ) u1 , r1 = ( fa * l . quo ( fd ) ) . div ( z ) # (l*f).div(z) u2 , r2 = ( wa * l . quo ( wd ) ) . div ( z ) # (l*w).div(z) eqs = [ r1 . nth ( i ) - c1 * r2 . nth ( i ) for i in range ( z . degree ( DE . t ) ) ] s = solve ( eqs , c1 ) if not s or not s [ c1 ] . is_Rational : # deg(q) <= B, no solution for c. return None M , N = s [ c1 ] . as_numer_denom ( ) nfmwa = N . as_poly ( DE . t ) * fa * wd - M . as_poly ( DE . t ) * wa * fd nfmwd = fd * wd Qv = is_log_deriv_k_t_radical_in_field ( nfmwa , nfmwd , DE ) if Qv is None : # (N*f - M*w) is not the logarithmic derivative of a k(t)-radical. return None Q , v = Qv if Q . is_zero or v . is_zero : # Q == 0 or v == 0. return None return ( Q * N , Q * M , v )