def test_order_at(): a = Poly(t**4, t) b = Poly((t**2 + 1)**3*t, t) p1 = Poly(t, t) p2 = Poly(1 + t**2, t) assert order_at(a, p1, t) == 4 assert order_at(b, p1, t) == 1 assert order_at(a, p2, t) == 0 assert order_at(b, p2, t) == 3 assert order_at(Poly(0, t), Poly(t, t), t) == oo assert order_at_oo(Poly(t**2 - 1, t), Poly(t + 1), t) == \ order_at_oo(Poly(t - 1, t), Poly(1, t), t) == -1 assert order_at_oo(Poly(0, t), Poly(1, t), t) == oo
# 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:
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)
def test_order_at(): a = Poly(t**4, t) b = Poly((t**2 + 1)**3*t, t) c = Poly((t**2 + 1)**6*t, t) d = Poly((t**2 + 1)**10*t**10, t) e = Poly((t**2 + 1)**100*t**37, t) p1 = Poly(t, t) p2 = Poly(1 + t**2, t) assert order_at(a, p1, t) == 4 assert order_at(b, p1, t) == 1 assert order_at(c, p1, t) == 1 assert order_at(d, p1, t) == 10 assert order_at(e, p1, t) == 37 assert order_at(a, p2, t) == 0 assert order_at(b, p2, t) == 3 assert order_at(c, p2, t) == 6 assert order_at(d, p1, t) == 10 assert order_at(e, p2, t) == 100 assert order_at(Poly(0, t), Poly(t, t), t) == oo assert order_at_oo(Poly(t**2 - 1, t), Poly(t + 1), t) == \ order_at_oo(Poly(t - 1, t), Poly(1, t), t) == -1 assert order_at_oo(Poly(0, t), Poly(1, t), t) == oo
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': # alpha = (-b/a).rem(p) == -b(0)/a(0) # if alpha == m*Dt/t + Dz/z # parametric logarithmic derivative problem # n = min(n, m) # elif case == 'tan': # alpha*sqrt(-1) + beta = (-b/a)/rem(p) == -b(sqrt(-1))/a(sqrt(-1)) # eta = derivation(t, DE).quo(Poly(t**2 + 1, t)) # eta in k # if 2*beta == Db/b for some v in k* (see pg. 176) and \ # alpha*sqrt(-1) + beta == 2*b*eta*sqrt(-1) + Dz/z: # # parametric logarithmic derivative problem # n = min(n, m) raise NotImplementedError("The ability to solve the parametric " "logarithmic derivative problem is required to solve this PRDE.") 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)