def test_recognize_log_derivative(): a = Poly(2 * x**2 + 4 * x * t - 2 * t - x**2 * t, t) d = Poly((2 * x + t) * (t + x**2), t) DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]}) assert recognize_log_derivative(a, d, DE, z) == True DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1 / x, t)]}) assert recognize_log_derivative(Poly(t + 1, t), Poly(t + x, t), DE) == True assert recognize_log_derivative(Poly(2, t), Poly(t**2 - 1), DE) == True DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1, t)]}) assert recognize_log_derivative(Poly(1, t), Poly(t**2 - 2), DE) == False assert recognize_log_derivative(Poly(1, t), Poly(t**2 + t), DE) == True
def test_recognize_log_derivative(): a = Poly(2*x**2 + 4*x*t - 2*t - x**2*t, t) d = Poly((2*x + t)*(t + x**2), t) DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]}) assert recognize_log_derivative(a, d, DE, z) == True DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]}) assert recognize_log_derivative(Poly(t + 1, t), Poly(t + x, t), DE) == True assert recognize_log_derivative(Poly(2, t), Poly(t**2 - 1), DE) == True DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1, t)]}) assert recognize_log_derivative(Poly(1, t), Poly(t**2 - 2), DE) == False assert recognize_log_derivative(Poly(1, t), Poly(t**2 + t), DE) == True
DE.t) etaa, etad = frac_in(dcoeff, DE.t) A = parametric_log_deriv(alphaa, alphad, etaa, etad, DE) if A is not None: a, m, z = A if a == 1: n = min(n, m) elif case == 'tan': dcoeff = DE.d.quo(Poly(DE.t**2 + 1, DE.t)) with DecrementLevel(DE): # We are guaranteed to not have problems, # because case != 'base'. betaa, alphaa, alphad = real_imag(ba, bd * a, DE.t) betad = alphad etaa, etad = frac_in(dcoeff, DE.t) if recognize_log_derivative(2 * betaa, betad, DE): A = parametric_log_deriv(alphaa, alphad, etaa, etad, DE) B = parametric_log_deriv(betaa, betad, etaa, etad, DE) if A is not None and B is not None: a, s, z = A if a == 1: n = min(n, s / 2) N = max(0, -nb) pN = p**N pn = p**-n # This is 1/h A = a * pN B = ba * pN.quo(bd) + Poly(n, DE.t) * a * derivation(p, DE).quo(p) * pN G = [(Ga * pN * pn).cancel(Gd, include=True) for Ga, Gd in G] h = pn
def prde_special_denom(a, ba, bd, G, DE, case='auto'): """ Parametric Risch Differential Equation - Special part of the denominator. case is on of {'exp', 'tan', 'primitive'} for the hyperexponential, hypertangent, and primitive cases, respectively. For the hyperexponential (resp. hypertangent) case, given a derivation D on k[t] and a in k[t], b in k<t>, and g1, ..., gm in k(t) with Dt/t in k (resp. Dt/(t**2 + 1) in k, sqrt(-1) not in k), a != 0, and gcd(a, t) == 1 (resp. gcd(a, t**2 + 1) == 1), return the tuple (A, B, GG, h) such that A, B, h in k[t], GG = [gg1, ..., ggm] in k(t)^m, and for any solution c1, ..., cm in Const(k) and q in k<t> of a*Dq + b*q == Sum(ci*gi, (i, 1, m)), r == q*h in k[t] satisfies A*Dr + B*r == Sum(ci*ggi, (i, 1, m)). For case == 'primitive', k<t> == k[t], so it returns (a, b, G, 1) in this case. """ # TODO: Merge this with the very similar special_denom() in rde.py if case == 'auto': case = DE.case if case == 'exp': p = Poly(DE.t, DE.t) elif case == 'tan': p = Poly(DE.t**2 + 1, DE.t) elif case in ['primitive', 'base']: B = ba.quo(bd) return (a, B, G, Poly(1, DE.t)) else: raise ValueError("case must be one of {'exp', 'tan', 'primitive', " "'base'}, not %s." % case) nb = order_at(ba, p, DE.t) - order_at(bd, p, DE.t) nc = min([order_at(Ga, p, DE.t) - order_at(Gd, p, DE.t) for Ga, Gd in G]) n = min(0, nc - min(0, nb)) if not nb: # Possible cancellation. if case == 'exp': dcoeff = DE.d.quo(Poly(DE.t, DE.t)) with DecrementLevel(DE): # We are guaranteed to not have problems, # because case != 'base'. alphaa, alphad = frac_in(-ba.eval(0)/bd.eval(0)/a.eval(0), DE.t) etaa, etad = frac_in(dcoeff, DE.t) A = parametric_log_deriv(alphaa, alphad, etaa, etad, DE) if A is not None: a, m, z = A if a == 1: n = min(n, m) elif case == 'tan': dcoeff = DE.d.quo(Poly(DE.t**2 + 1, DE.t)) with DecrementLevel(DE): # We are guaranteed to not have problems, # because case != 'base'. betaa, alphaa, alphad = real_imag(ba, bd*a, DE.t) betad = alphad etaa, etad = frac_in(dcoeff, DE.t) if recognize_log_derivative(2*betaa, betad, DE): A = parametric_log_deriv(alphaa, alphad, etaa, etad, DE) B = parametric_log_deriv(betaa, betad, etaa, etad, DE) if A is not None and B is not None: a, s, z = A if a == 1: n = min(n, s/2) N = max(0, -nb) pN = p**N pn = p**-n # This is 1/h A = a*pN B = ba*pN.quo(bd) + Poly(n, DE.t)*a*derivation(p, DE).quo(p)*pN G = [(Ga*pN*pn).cancel(Gd, include=True) for Ga, Gd in G] h = pn # (a*p**N, (b + n*a*Dp/p)*p**N, g1*p**(N - n), ..., gm*p**(N - n), p**-n) return (A, B, G, h)
if Q == 1: n = min(n, m) elif case == 'tan': dcoeff = DE.d.quo(Poly(DE.t**2 + 1, DE.t)) with DecrementLevel(DE): # We are guaranteed to not have problems, # because case != 'base'. alphaa, alphad = frac_in( im(-ba.eval(sqrt(-1)) / bd.eval(sqrt(-1)) / a.eval(sqrt(-1))), DE.t) betaa, betad = frac_in( re(-ba.eval(sqrt(-1)) / bd.eval(sqrt(-1)) / a.eval(sqrt(-1))), DE.t) etaa, etad = frac_in(dcoeff, DE.t) if recognize_log_derivative(Poly(2, DE.t) * betaa, betad, DE): A = parametric_log_deriv( alphaa * Poly(sqrt(-1), DE.t) * betad + alphad * betaa, alphad * betad, etaa, etad, DE) if A is not None: Q, m, z = A if Q == 1: n = min(n, m) N = max(0, -nb, n - nc) pN = p**N pn = p**-n A = a * pN B = ba * pN.quo(bd) + Poly(n, DE.t) * a * derivation(p, DE).quo(p) * pN C = (ca * pN * pn).quo(cd) h = pn