def test_Modules(): from sympy.polys.domains import QQ from sympy.polys.agca import homomorphism R = QQ.old_poly_ring(x, y) F = R.free_module(2) M = F.submodule([x, y], [1, x**2]) assert latex(F) == r"{\mathbb{Q}\left[x, y\right]}^{2}" assert latex(M) == \ r"\left< {\left[ {x},{y} \right]},{\left[ {1},{x^{2}} \right]} \right>" I = R.ideal(x**2, y) assert latex(I) == r"\left< {x^{2}},{y} \right>" Q = F / M assert latex( Q ) == r"\frac{{\mathbb{Q}\left[x, y\right]}^{2}}{\left< {\left[ {x},{y} \right]},{\left[ {1},{x^{2}} \right]} \right>}" assert latex(Q.submodule([1, x**3/2], [2, y])) == \ r"\left< {{\left[ {1},{\frac{x^{3}}{2}} \right]} + {\left< {\left[ {x},{y} \right]},{\left[ {1},{x^{2}} \right]} \right>}},{{\left[ {2},{y} \right]} + {\left< {\left[ {x},{y} \right]},{\left[ {1},{x^{2}} \right]} \right>}} \right>" h = homomorphism( QQ.old_poly_ring(x).free_module(2), QQ.old_poly_ring(x).free_module(2), [0, 0]) assert latex( h ) == r"{\left[\begin{matrix}0 & 0\\0 & 0\end{matrix}\right]} : {{\mathbb{Q}\left[x\right]}^{2}} \to {{\mathbb{Q}\left[x\right]}^{2}}"
def test_conversion(): L = QQ.old_poly_ring(x, y, order="ilex") G = QQ.old_poly_ring(x, y) assert L.convert(x) == L.convert(G.convert(x), G) assert G.convert(x) == G.convert(L.convert(x), L) raises(CoercionFailed, lambda: G.convert(L.convert(1/(1 + x)), L))
def test_Modules(): from sympy.polys.domains import QQ from sympy.polys.agca import homomorphism R = QQ.old_poly_ring(x, y) F = R.free_module(2) M = F.submodule([x, y], [1, x ** 2]) assert latex(F) == r"{\mathbb{Q}\left[x, y\right]}^{2}" assert latex(M) == r"\left< {\left[ {x},{y} \right]},{\left[ {1},{x^{2}} \right]} \right>" I = R.ideal(x ** 2, y) assert latex(I) == r"\left< {x^{2}},{y} \right>" Q = F / M assert ( latex(Q) == r"\frac{{\mathbb{Q}\left[x, y\right]}^{2}}{\left< {\left[ {x},{y} \right]},{\left[ {1},{x^{2}} \right]} \right>}" ) assert ( latex(Q.submodule([1, x ** 3 / 2], [2, y])) == r"\left< {{\left[ {1},{\frac{x^{3}}{2}} \right]} + {\left< {\left[ {x},{y} \right]},{\left[ {1},{x^{2}} \right]} \right>}},{{\left[ {2},{y} \right]} + {\left< {\left[ {x},{y} \right]},{\left[ {1},{x^{2}} \right]} \right>}} \right>" ) h = homomorphism(QQ.old_poly_ring(x).free_module(2), QQ.old_poly_ring(x).free_module(2), [0, 0]) assert ( latex(h) == r"{\left[\begin{matrix}0 & 0\\0 & 0\end{matrix}\right]} : {{\mathbb{Q}\left[x\right]}^{2}} \to {{\mathbb{Q}\left[x\right]}^{2}}" )
def test_GlobalPolynomialRing_convert(): K1 = QQ.old_poly_ring(x) K2 = QQ[x] assert K1.convert(x) == K1.convert(K2.convert(x), K2) assert K2.convert(x) == K2.convert(K1.convert(x), K1) K1 = QQ.old_poly_ring(x, y) K2 = QQ[x] assert K1.convert(x) == K1.convert(K2.convert(x), K2) #assert K2.convert(x) == K2.convert(K1.convert(x), K1) K1 = ZZ.old_poly_ring(x, y) K2 = QQ[x] assert K1.convert(x) == K1.convert(K2.convert(x), K2)
def test_QuotientRing(): from sympy.polys.domains import QQ R = QQ.old_poly_ring(x) / [x**2 + 1] assert latex( R) == r"\frac{\mathbb{Q}\left[x\right]}{\left< {x^{2} + 1} \right>}" assert latex(R.one) == r"{1} + {\left< {x^{2} + 1} \right>}"
def test_QuotientRing(): from sympy.polys.domains import QQ R = QQ.old_poly_ring(x)/[x**2 + 1] assert latex( R) == r"\frac{\mathbb{Q}\left[x\right]}{\left< {x^{2} + 1} \right>}" assert latex(R.one) == r"{1} + {\left< {x^{2} + 1} \right>}"
def test_globalring(): Qxy = QQ.old_frac_field(x, y) R = QQ.old_poly_ring(x, y) X = R.convert(x) Y = R.convert(y) assert x in R assert 1/x not in R assert 1/(1 + x) not in R assert Y in R assert X.ring == R assert X * (Y**2 + 1) == R.convert(x * (y**2 + 1)) assert X * y == X * Y == R.convert(x * y) == x * Y assert X + y == X + Y == R.convert(x + y) == x + Y assert X - y == X - Y == R.convert(x - y) == x - Y assert X + 1 == R.convert(x + 1) raises(ExactQuotientFailed, lambda: X/Y) raises(ExactQuotientFailed, lambda: x/Y) raises(ExactQuotientFailed, lambda: X/y) assert X**2 / X == X assert R.from_GlobalPolynomialRing(ZZ.old_poly_ring(x, y).convert(x), ZZ.old_poly_ring(x, y)) == X assert R.from_FractionField(Qxy.convert(x), Qxy) == X assert R.from_FractionField(Qxy.convert(x)/y, Qxy) is None assert R._sdm_to_vector(R._vector_to_sdm([X, Y], R.order), 2) == [X, Y]
def test_localring(): Qxy = QQ.old_frac_field(x, y) R = QQ.old_poly_ring(x, y, order="ilex") X = R.convert(x) Y = R.convert(y) assert x in R assert 1/x not in R assert 1/(1 + x) in R assert Y in R assert X.ring == R assert X*(Y**2 + 1)/(1 + X) == R.convert(x*(y**2 + 1)/(1 + x)) assert X*y == X*Y raises(ExactQuotientFailed, lambda: X/Y) raises(ExactQuotientFailed, lambda: x/Y) raises(ExactQuotientFailed, lambda: X/y) assert X + y == X + Y == R.convert(x + y) == x + Y assert X - y == X - Y == R.convert(x - y) == x - Y assert X + 1 == R.convert(x + 1) assert X**2 / X == X assert R.from_GlobalPolynomialRing(ZZ.old_poly_ring(x, y).convert(x), ZZ.old_poly_ring(x, y)) == X assert R.from_FractionField(Qxy.convert(x), Qxy) == X raises(CoercionFailed, lambda: R.from_FractionField(Qxy.convert(x)/y, Qxy)) raises(ExactQuotientFailed, lambda: X/Y) raises(NotReversible, lambda: X.invert()) assert R._sdm_to_vector( R._vector_to_sdm([X/(X + 1), Y/(1 + X*Y)], R.order), 2) == \ [X*(1 + X*Y), Y*(1 + X)]
def test_units(): R = QQ.old_poly_ring(x) assert R.is_unit(R.convert(1)) assert R.is_unit(R.convert(2)) assert not R.is_unit(R.convert(x)) assert not R.is_unit(R.convert(1 + x)) R = QQ.old_poly_ring(x, order='ilex') assert R.is_unit(R.convert(1)) assert R.is_unit(R.convert(2)) assert not R.is_unit(R.convert(x)) assert R.is_unit(R.convert(1 + x)) R = ZZ.old_poly_ring(x) assert R.is_unit(R.convert(1)) assert not R.is_unit(R.convert(2)) assert not R.is_unit(R.convert(x)) assert not R.is_unit(R.convert(1 + x))
def _create_table(table): """ Creates the look-up table. For a similar implementation see meijerint._create_lookup_table. """ def add(formula, annihilator, arg, x0=0, y0=[]): """ Adds a formula in the dictionary """ table.setdefault(_mytype(formula, x_1), []).append((formula, HolonomicFunction(annihilator, arg, x0, y0))) R = QQ.old_poly_ring(x_1) _, Dx = DifferentialOperators(R, 'Dx') from sympy import (sin, cos, exp, log, erf, sqrt, pi, sinh, cosh, sinc, erfc, Si, Ci, Shi, erfi) # add some basic functions add(sin(x_1), Dx**2 + 1, x_1, 0, [0, 1]) add(cos(x_1), Dx**2 + 1, x_1, 0, [1, 0]) add(exp(x_1), Dx - 1, x_1, 0, 1) add(log(x_1), Dx + x_1*Dx**2, x_1, 1, [0, 1]) add(erf(x_1), 2*x_1*Dx + Dx**2, x_1, 0, [0, 2/sqrt(pi)]) add(erfc(x_1), 2*x_1*Dx + Dx**2, x_1, 0, [1, -2/sqrt(pi)]) add(erfi(x_1), -2*x_1*Dx + Dx**2, x_1, 0, [0, 2/sqrt(pi)]) add(sinh(x_1), Dx**2 - 1, x_1, 0, [0, 1]) add(cosh(x_1), Dx**2 - 1, x_1, 0, [1, 0]) add(sinc(x_1), x_1 + 2*Dx + x_1*Dx**2, x_1) add(Si(x_1), x_1*Dx + 2*Dx**2 + x_1*Dx**3, x_1) add(Ci(x_1), x_1*Dx + 2*Dx**2 + x_1*Dx**3, x_1) add(Shi(x_1), -x_1*Dx + 2*Dx**2 + x_1*Dx**3, x_1)
def _convert_poly_rat(func, x, initcond=True): """Converts Polynomials and Rationals to Holonomic. """ ispoly = func.is_polynomial() if not ispoly: israt = func.is_rational_function() else: israt = True if not (ispoly or israt): return None R = QQ.old_poly_ring(x) _, Dx = DifferentialOperators(R, 'Dx') if ispoly: # differential equation satisfied by polynomial sol = func * Dx - func.diff() sol = _normalize(sol.listofpoly, sol.parent, negative=False) elif israt: order = 1 p, q = func.as_numer_denom() # differential equation satisfied by rational sol = p * q * Dx + p * q.diff() - q * p.diff() sol = _normalize(sol.listofpoly, sol.parent, negative=False) if not initcond: return HolonomicFunction(sol, x) x0 = 0 y0 = _find_conditions(func, x, x0, sol.order) while not y0: x0 += 1 y0 = _find_conditions(func, x, x0, sol.order) return HolonomicFunction(sol, x, x0, y0)
def from_hyper(func, x0=0, evalf=False): """ Converts Hypergeometric Function to Holonomic. func is the Hypergeometric Function and x0 be the point at which initial conditions are required. Examples ======= >>> from sympy.holonomic.holonomic import from_hyper, DifferentialOperators >>> from sympy import symbols, hyper, S >>> x = symbols('x') >>> from_hyper(hyper([], [S(3)/2], x**2/4)) HolonomicFunction((-x) + (2)Dx + (x)Dx**2, x), f(1) = sinh(1) , f'(1) = -sinh(1) + cosh(1) """ a = func.ap b = func.bq z = func.args[2] x = z.atoms(Symbol).pop() R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx') r1 = 1 for i in range(len(a)): r1 = r1 * (x * Dx + a[i]) r2 = Dx for i in range(len(b)): r2 = r2 * (x * Dx + b[i] - 1) sol = r1 - r2 simp = hyperexpand(func) if isinstance(simp, Infinity) or isinstance(simp, NegativeInfinity): return HolonomicFunction(sol, x).composition(z) def _find_conditions(simp, x, x0, order, evalf=False): y0 = [] for i in range(order): if evalf: val = simp.subs(x, x0).evalf() else: val = simp.subs(x, x0) if isinstance(val, Infinity) or isinstance(val, NaN): return None y0.append(val) simp = simp.diff() return y0 if not isinstance(simp, hyper): y0 = _find_conditions(simp, x, x0, sol.order) while not y0: x0 += 1 y0 = _find_conditions(simp, x, x0, sol.order) return HolonomicFunction(sol, x, x0, y0).composition(z) if isinstance(simp, hyper): x0 = 1 y0 = _find_conditions(simp, x, x0, sol.order, evalf) while not y0: x0 += 1 y0 = _find_conditions(simp, x, x0, sol.order, evalf) return HolonomicFunction(sol, x, x0, y0).composition(z) return HolonomicFunction(sol, x).composition(z)
def test_PolynomialRingBase(): from sympy.polys.domains import QQ assert latex(QQ.old_poly_ring(x, y)) == r"\mathbb{Q}\left[x, y\right]" assert latex(QQ.old_poly_ring(x, y, order="ilex")) == \ r"S_<^{-1}\mathbb{Q}\left[x, y\right]"
def from_hyper(func, x0=0, evalf=False): """ Converts Hypergeometric Function to Holonomic. func is the Hypergeometric Function and x0 be the point at which initial conditions are required. Examples ======= >>> from sympy.holonomic.holonomic import from_hyper, DifferentialOperators >>> from sympy import symbols, hyper, S >>> x = symbols('x') >>> from_hyper(hyper([], [S(3)/2], x**2/4)) HolonomicFunction((-x) + (2)Dx + (x)Dx**2, x), f(1) = sinh(1), f'(1) = -sinh(1) + cosh(1) """ a = func.ap b = func.bq z = func.args[2] x = z.atoms(Symbol).pop() R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx') # generalized hypergeometric differential equation r1 = 1 for i in range(len(a)): r1 = r1 * (x * Dx + a[i]) r2 = Dx for i in range(len(b)): r2 = r2 * (x * Dx + b[i] - 1) sol = r1 - r2 simp = hyperexpand(func) if isinstance(simp, Infinity) or isinstance(simp, NegativeInfinity): return HolonomicFunction(sol, x).composition(z) def _find_conditions(simp, x, x0, order, evalf=False): y0 = [] for i in range(order): if evalf: val = simp.subs(x, x0).evalf() else: val = simp.subs(x, x0) # return None if it is Infinite or NaN if (val.is_finite is not None and not val.is_finite) or isinstance(val, NaN): return None y0.append(val) simp = simp.diff() return y0 # if the function is known symbolically if not isinstance(simp, hyper): y0 = _find_conditions(simp, x, x0, sol.order) while not y0: # if values don't exist at 0, then try to find initial # conditions at 1. If it doesn't exist at 1 too then # try 2 and so on. x0 += 1 y0 = _find_conditions(simp, x, x0, sol.order) return HolonomicFunction(sol, x).composition(z, x0, y0) if isinstance(simp, hyper): x0 = 1 # use evalf if the function can't be simpified y0 = _find_conditions(simp, x, x0, sol.order, evalf) while not y0: x0 += 1 y0 = _find_conditions(simp, x, x0, sol.order, evalf) return HolonomicFunction(sol, x).composition(z, x0, y0) return HolonomicFunction(sol, x).composition(z)
def test_build_order(): R = QQ.old_poly_ring(x, y, order=(("lex", x), ("ilex", y))) assert R.order((1, 5)) == ((1,), (-5,))
def from_meijerg(func, x0=0, evalf=False): """ Converts a Meijer G-function to Holonomic. func is the Hypergeometric Function and x0 be the point at which initial conditions are required. Examples ======= >>> from sympy.holonomic.holonomic import from_meijerg, DifferentialOperators >>> from sympy import symbols, meijerg, S >>> x = symbols('x') >>> from_meijerg(meijerg(([], []), ([S(1)/2], [0]), x**2/4)) HolonomicFunction((1) + (1)Dx**2, x), f(0) = 0, f'(0) = 1/sqrt(pi) """ a = func.ap b = func.bq n = len(func.an) m = len(func.bm) p = len(a) z = func.args[2] x = z.atoms(Symbol).pop() R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx') # compute the differential equation satisfied by the # Meijer G-function. mnp = (-1)**(m + n - p) r1 = x * mnp for i in range(len(a)): r1 *= x * Dx + 1 - a[i] r2 = 1 for i in range(len(b)): r2 *= x * Dx - b[i] sol = r1 - r2 simp = hyperexpand(func) if isinstance(simp, Infinity) or isinstance(simp, NegativeInfinity): return HolonomicFunction(sol, x).composition(z) def _find_conditions(simp, x, x0, order, evalf=False): y0 = [] for i in range(order): if evalf: val = simp.subs(x, x0).evalf() else: val = simp.subs(x, x0) if (val.is_finite is not None and not val.is_finite) or isinstance(val, NaN): return None y0.append(val) simp = simp.diff() return y0 # computing initial conditions if not isinstance(simp, meijerg): y0 = _find_conditions(simp, x, x0, sol.order) while not y0: x0 += 1 y0 = _find_conditions(simp, x, x0, sol.order) return HolonomicFunction(sol, x).composition(z, x0, y0) if isinstance(simp, meijerg): x0 = 1 y0 = _find_conditions(simp, x, x0, sol.order, evalf) while not y0: x0 += 1 y0 = _find_conditions(simp, x, x0, sol.order, evalf) return HolonomicFunction(sol, x).composition(z, x0, y0) return HolonomicFunction(sol, x).composition(z)